英文:
Is Calling the `Wait()` method of `sync.Cond` Concurrently, Safe?
问题
根据文档,调用sync.Cond
的Wait()
方法时会先执行Unlock()
,那么这样做是安全的吗?
假设我们正在检查是否满足某个条件:
func sample() {
cond = &sync.Cond{L: &sync.Mutex{}} // 可以被程序的其他部分访问
go func() {
cond.L.Lock()
for !condition() {
cond.Wait()
}
// 做一些操作...
cond.L.Unlock()
}()
go func() {
cond.L.Lock()
mutation()
cond.L.Unlock()
cond.Signal()
}()
}
以及:
func condition() bool {
// 假设someSharedState是一个比bool更复杂的状态
return someSharedState
}
func mutation() {
// 假设someSharedState是一个比bool更复杂的状态
// (A) 对someSharedState进行状态变更
}
由于Wait()
方法执行了Unlock()
,那么(A)是否需要自己进行加锁?还是说它是原子操作的?
英文:
Is calling the Wait()
method of sync.Cond
safe when according to the documentation, it performs an Unlock()
first?
Assume we are checking for a condition to be met:
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()
}()
}
And:
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
}
Since Wait()
performs an Unlock
, should (A) has a locking of it's own? Or being atomic?
答案1
得分: 2
是的,即使在调用Wait
时首先调用了L.Unlock()
,也是安全的,但在调用Wait
和检查条件之前,必须先获取锁,因为在这种情况下,两者都不是线程安全的。
Wait
会原子性地解锁c.L
并暂停调用的goroutine的执行。在稍后恢复执行之前,Wait
会重新锁定c.L
然后返回。
- 调用
Wait
的goroutine获取了锁,检查条件发现不满足。 - 现在它等待,但为了允许条件的更改,它需要释放锁。
Wait
会自动为您完成这个步骤,然后暂停goroutine的执行。 - 现在条件可以发生变化,最终goroutine会被
Broadcast
或Signal
唤醒。然后它会重新获取锁来再次检查条件(这必须逐个进行,以便每个等待的goroutine都能进行检查,否则将无法知道有多少个goroutine现在自由运行)。
英文:
Yes it is safe to call Wait
even when it calls L.Unlock()
first but it is essential that you acquired the lock before calling Wait
and before checking your condition since, in this situation, both are not thread safe.
> Wait
atomically unlocks c.L
and suspends execution of the calling goroutine. After later resuming execution, Wait
locks c.L
before returning.
- The goroutine that calls
Wait
acquired the lock, checked the condition and found it to be unsatisfactory. - Now it waits but in order to allow for changes of the condition it needs to give the lock back.
Wait
does that automatically for you and then suspends the goroutine. - Now changes of the condition can happen and eventually the goroutine is awoken by
Broadcast
orSignal
. It then acquires the lock to check the condition once again (This must happen one-by-one for each waiting goroutine or else there would be no way telling how many goroutines are running around freely now).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论