Go 如何给某个协程加锁(不允许开新的协程)

问题描述

1.可能我的题目描述的不太清除,这里详细描述一下

项目是用 beego 开发的,其中在控制器中又一个方法

//同步图片
func (this *ApiController) SyncImages() {
.
.
.
go models.TestSyncImages(images)
.
.
.
}

在另外一个 models包里面有上述协程调用的方法

func TestSyncImages(list []SyncImage) {
    var image = auxpi.Image{}
    var wg sync.WaitGroup
    for _, value := range list {
        go func(url string, id uint) {
            wg.Add(1)
            defer wg.Done()
            res, _ := http.Get(url)
            lUrl, name, del := localStoreInfo(res.Header.Get("Content-Type"), url)
            dst, _ := os.Create(name)
            io.Copy(dst, res.Body)
            image.ID = id
            image.Url = lUrl
            image.Delete = del
            AddSyncImage(image)
            
        }(value.External, value.ImageID)
    }
    wg.Wait()

}

工作流程是:

用户提交同步图片的命令->控制器接到数据 SyncImages() 方法->SyncImages() 启用协程去执行 TestSyncImages()方法

但是现在出了一个问题,如果用户同时点击两次甚至多次,会出现重复进入TestSyncImages(),会扰乱当前所在的工作的协程,如果点击多次甚至会出现内存溢出的状况。

请问各位,如何保证 TestSyncImages() 这个方法不会被多次执行,有什么办法给这个东西加锁,或者使用别的更好的方法解决?

阅读 4.4k
3 个回答

这种我建议你在SyncImages方法中按照用户ID加缓存判断,比如1分钟只能点一次,那点击的时候检测有没有这个缓存,如果有,则不同步,如果没有则写入缓存后同步

我想你需要的是单例模式。看一下这篇文章

如果是个单机程序,推荐使用 sync.Once, 如果是分布式服务器上,推荐使用 redis 的 setnx 指令,加一个锁。可以百度搜索下,参考下 https://www.jianshu.com/p/c97... 这种类似的文章

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题