Condition variables are generally used such that the state they refer to is modified under a mutex. However, when the state is just a single set-only flag, there's no need for a mutex to prevent simultaneous execution. So one might want to do something like this:
flag = 1;
pthread_cond_broadcast(&cvar);
However, this is only safe if pthread_cond_broadcast implies a write memory barrier; otherwise, the waiting thread may see the condition variable broadcast before the flag write. That is, the waiting thread may awaken, consume the cvar signal, but see the flag still 0.
So, my question is: Do the pthread_cond_broadcast and pthread_cond_signal calls imply a write memory barrier? If so, where is this specified in the relevant POSIX (or other) specifications? The spec seemed unclear on this point.
Note: I am aware that, in practice, this does result in a memory barrier (on Linux, because thread awakening implies a full CPU memory barrier, and the cross-library function call implies a compiler memory barrier). However, I'm interested here in what the spec guarentees.
Regardless of whether it implies a memory barrier, the code is still not correct. Consider the read side:
while (flag == 0)
pthread_cond_wait(&cvar, &mutex);
If the read side is suspended between testing flag == 0 and executing the wait, the write side can execute the flag = 1; pthread_cond_signal(&cvar);. The read side will then miss the wakeup entirely - it will wait forever. Remember that wakeups are not queued - if there's no waiter when the condition variable is signalled, the signal has no effect. To avoid this, the write side needs to lock the mutex anyway.
Under POSIX, if you write to a variable from one thread and read it from another then you must protect it with a mutex. There is no exception made for pthread_cond_broadcast.
If your platform/compiler offer atomic variables then they may make additional guarantees about those. For example, if flag is a C++11 std::atomic<int> then this code is OK.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With