正确使用sync.Cond进行条件等待
在探索sync.Cond的功能时,很明显可能会出现竞争条件锁定sync.Mutex 和调用cond.Wait 之间。为了证明这一点,在主 Goroutine 中引入了人为延迟,模拟竞争条件:
package main import ( "sync" "time" ) func main() { var m sync.Mutex var c = sync.NewCond(&m) go func() { time.Sleep(1 * time.Second) c.Broadcast() }() m.Lock() time.Sleep(2 * time.Second) c.Wait() }
执行此代码会导致死锁恐慌,因为 goroutine 正在等待尚未发出信号的条件.
解决竞争条件
避免这种竞争条件的正确方法是确保在调用 cond.Wait 之前锁定sync.Mutex。这可以防止当前 Goroutine 在等待某个条件时其他 Goroutine 修改共享数据:
package main import ( "sync" "time" ) func main() { var m sync.Mutex var c = sync.NewCond(&m) go func() { time.Sleep(1 * time.Second) m.Lock() c.Broadcast() m.Unlock() }() m.Lock() c.Wait() m.Unlock() }
替代同步构造
虽然sync.Cond 很有用在多个 goroutine 等待共享资源变得可用的情况下,考虑替代同步原语非常重要。例如,如果编写者和读者之间存在一对一的关系,则sync.Mutex可能足以进行通信:
var sharedRsc = make(map[string]interface{}) func main() { m := sync.Mutex{} go func() { m.Lock() sharedRsc["rsc1"] = "foo" m.Unlock() }() m.Lock() fmt.Println(sharedRsc["rsc1"]) m.Unlock() }
在涉及多个读者的情况下,通道提供了更有效的方式用于传递数据的可扩展解决方案。
以上是使用sync.Cond进行条件等待时如何避免竞争条件?的详细内容。更多信息请关注PHP中文网其他相关文章!