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?
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 unlocksc.L
and suspends execution of the calling goroutine. After later resuming execution,Wait
locksc.L
before returning.
Wait
acquired the lock, checked the condition and found it to be unsatisfactory. Wait
does that automatically for you and then suspends the goroutine. Broadcast
or Signal
. 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).