boost::condition_variable and lock

2019-05-18 07:32发布

问题:

boost::condition_variable cond;
boost::mutex mut;

//thread1
{
"read_socket()"
cond.notify_one();
}

//thread2
{
for(;;)
{
...
boost::unique_lock<boost::mutex> lock(mut);
cond.wait(lock);
}
}

versus

boost::condition_variable cond;
boost::mutex mut;

//thread1
{
"read_socket()"
boost::unique_lock<boost::mutex> lock(mut);
cond.notify_one();
}

//thread2
{
for(;;)
{
...
boost::unique_lock<boost::mutex> lock(mut);
cond.wait(lock);
}

Is there an impact if I omit the lock before calling cond.notify_one() ?

回答1:

The C++11 standard does not state any requirement for notify_one and notify_all; so not holding the lock when you signal a condition_variable is fine. However, it's often necessary for the signaling thread to hold the lock until it sets the condition checked by the waiting thread after it's woken up. If it does not, the program may contain races. For an example, see this SO question: Boost synchronization.



回答2:

When thread2 is waking, it will attempt to re-aquire the lock. If thread1 is holding the lock, thread2 will block until thread1 releases the lock.

In the code shown here, this doesn't significantly impact behavior. If you were to add any behavior in thread1 after cond.notify_one();, that behavior would be guaranteed to execute before thread2 proceeds in the second code block only.

Alternatively, you could construct the unique lock in thread2 before entering the for loop, rather than just before waiting on the condition variable. This would ensure that thread1 blocks when trying to construct its own unique lock until thread2 is waiting for a signal, provided that thread1 is not executing before thread2 has initialized itself and entered the loop. This would allow you to guarantee that thread1 doesn't send any notifications that thread2 isn't waiting for.