Dictionary 使用sync.Map确保只有一个goroutine正在运行
我有一个HTTP处理程序,它从查询接收一个参数。我不想为同一查询参数同时运行此处理程序,即在一个时间点上只应运行一个goroutine 这是我的想法:Dictionary 使用sync.Map确保只有一个goroutine正在运行,dictionary,go,concurrency,synchronization,locking,Dictionary,Go,Concurrency,Synchronization,Locking,我有一个HTTP处理程序,它从查询接收一个参数。我不想为同一查询参数同时运行此处理程序,即在一个时间点上只应运行一个goroutine 这是我的想法: import "sync" import "fmt" var safeMap = sync.Map{} func handler(c) { _, loaded := safeMap.LoadOrStore(c.param, 1) // loaded is true if value was loaded and false if s
import "sync"
import "fmt"
var safeMap = sync.Map{}
func handler(c) {
_, loaded := safeMap.LoadOrStore(c.param, 1) // loaded is true if value was loaded and false if stored
fmt.Println(loaded)
if loaded {
c.JSON(http.StatusLocked, "locked")
return
}
go doWork(c.param)
safeMap.Delete(c.param)
c.JSON(http.StatusOK, "done")
}
但是,无论何时发送两个已加载的并发请求,这两个请求都为false,并且这两个请求都会得到处理。为什么?问题是你在一个新的工作环境中工作。如果param尚未锁定,则处理程序将其锁定,并启动一个goroutine来执行该工作。但是服务于请求的goroutine不会等待工作完成,它会立即解锁param 相反,在处理程序中执行该工作,因此只有在doWork返回时才会解锁参数:
您正在启动一个goroutine来完成工作,然后在工作有机会完成之前立即删除密钥。因此,锁争用的可能性非常小
为什么要使用go doWork而不是doWork?因为doWork需要很长时间,我不希望请求等待。这更像是一个异步任务。然后,您还需要将锁管理移到该goroutine中。
doWork(c.param) // Note no 'go' keyword