问题
I'll present some code first since explaining is easier that way. Assume that mutexes are correctly used with the condition variables to keep it simple:
// Thread 1
while(1)
{
conditionVariable.wait();
// Do some work
}
// Thread 2
while(1)
{
// Do some work
conditionVariable.notify_one();
}
// Thread 3
while(1)
{
// Do some work
conditionVariable.notify_one();
}
What I would like to achieve is that thread 1 is guaranteed to be waiting on the condition variable when thread 2 or Thread 3 notifies. As the code stands, there is a large gap between notify_one()
and wait()
in the form of some other code marked by the comments. This gap means sometimes notify_one()
is called before gets a chance to call wait()
.
After some thought it seems that the closest I can get to this is to use some form of mutual exclusion before notify_one()
and before wait()
(at the start of thread 1's loop). However, no matter how this is done, there is still a small gap (1 line of code) between the mutual exclusion and the wait()
, allowing Threads 2 and 3 to call notify_one()
just before Thread 1 calls wait()
. It's unlikely, but possible.
I also thought about using the wait()
predicate to flag a boolean allowing the other threads to notify. I guess this would work since wait()
is atomic, but I'm wondering if there is a better way. Perhaps I am approaching this incorrectly.
In summary: how can I ensure thread 1 is waiting before allowing threads 2 and 3 to notify?
回答1:
In short: think about condition variables as a method to notify other threads that something has changed, not just as a signal.
In order to do this, the condition variable should accompany a condition (simple example: an integer is incremented) that can be handled by the receiving thread.
Now, to solve your problem, thread 1 can use a condition variable accompanied by a ready boolean to signal the other threads when it is ready to receive the condition variable signal, but you better check first whether the original condition variable can be used as described here.
pseudo code based on question (proper locking of conditionVariable still needed):
// Thread 1
while(1)
{
lockReady();
ready = true;
unlockReady();
readyCV.notify_one();
conditionVariable.wait();
// Do some work
}
// Thread 2
while(1)
{
lockReady();
while (! ready) readyCV.wait();
ready = false;
unlockReady();
// Do some work
conditionVariable.notify_one();
}
// Thread 3
while(1)
{
lockReady();
while (! ready) readyCV.wait();
ready = false;
unlockReady();
// Do some work
conditionVariable.notify_one();
}
see also my previous answer
来源:https://stackoverflow.com/questions/21304375/condition-variable-wait-notify-race-condition