确保只有一个 goroutine 在使用同步运行.地图



我有一个从查询接收参数的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 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")
}

但是,每当我发送两个并发请求时loaded这两个请求都是假的,并且两个请求都被处理了。为什么?

问题是你在一个新的goroutine中做你的工作(doWork())。如果参数尚未锁定,处理程序将锁定它,并启动一个 goroutine 来完成工作。但是为请求提供服务的 goroutine 不会等待工作完成,它会立即解锁参数。

而是在处理程序中执行工作,因此解锁参数只会在返回doWork()发生:

doWork(c.param) // Note no 'go' keyword

您正在启动一个 goroutine 来完成工作,然后在工作有机会完成之前立即删除密钥。 因此,锁争用的几率极低。

为什么使用go doWork()而不仅仅是doWork()

最新更新