根据文档,首先执行Unlock()
时,调用sync.Cond
的Wait()
方法是否安全?
假设我们正在检查要满足的条件:
func sample() {
cond = &sync.Cond{L: &sync.Mutex{}} // accessible by other parts of program
go func() {
cond.L.Lock()
for !condition() {
cond.Wait()
}
// do stuff ...
cond.L.Unlock()
}()
go func() {
cond.L.Lock()
mutation()
cond.L.Unlock()
cond.Signal()
}()
}
和:
func condition() bool {
// assuming someSharedState is a more complex state than just a bool
return someSharedState
}
func mutation() {
// assuming someSharedState is a more complex state than just a bool
// (A) state mutation on someSharedState
}
既然Wait()
执行Unlock
,(A)是否应该有自己的锁定?还是原子?
是的,即使先调用L.Unlock()
,也可以安全地调用Wait
,但必须在调用Wait
之前和检查条件之前获取锁,因为在这种情况下,两者都不是线程安全的。
Wait
原子地解锁c.L
并挂起调用goroutine的执行稍后恢复执行后,Wait
在返回之前锁定c.L
。
- 调用
Wait
的goroutine获取了锁,检查了条件,发现它不符合要求 - 现在它在等待,但为了允许条件的更改,它需要归还锁。
Wait
会自动为您执行此操作,然后挂起goroutine - 现在可以发生条件的更改,并且最终由
Broadcast
或Signal
唤醒goroutine。然后,它获取锁以再次检查条件(这必须对每个等待的goroutine逐一进行,否则就无法判断现在有多少goroutine在自由运行)