> In theory, a condition variable like sync.Cond doesn’t have to be tied to a lock for its signaling to work. > You could have the users manage their own locks outside of the condition variable, which might sound like it gives more flexibility. It’s not really a technical limitation but more about human error.
I don't think this is true, if the concurrency model for goroutines may be assumed to be the same as regular OS threads. Assume the following:
1. You lock a shared resource (to be progressed by a worker goroutine)
2. You spawn the worker goroutine
3. You unlock the shared resource
4. It just so happens that the go runtime schedules the worker on a separate CPU, the worker now then progresses the resource to completion, and cond.Broadcast()'s
5. You now cond.Wait'() on a signal that will never arrive. (This cannot actually happen because Golang's cond.Wait() requires the lock to have been acquired before being called, and also locks before relinquishing control, so we're discussing the post author's version)
This was also the issue I noticed when I was considering using channels for signaling. The use case was:
1. I needed a worker goroutine that progressed a certain resource
2. I needed to fail anyway if the worker did not progress to completion at least within a timeout.
3. I needed to eagerly return asap if the worker progressed to completion before the timeout is done.
I initially considered spawning the worker goroutine and a timeout goroutine and doing a select on channels. But it turned out to be far easier done with a condition variable, especially if we needed to make sure that nothing eventually ends up blocking on sending to a channel that will never be listened to.