Using a lock with condition variables

2019-04-11 17:51发布

问题:

Consider the following simplistic example of condition variables:

bool pause = true;

boost::mutex::scoped_lock lock(m_mutex);
while (!pause) cv.wait(lock);

and

boost::mutex::scoped_lock lock(m_mutex);
pause = false;
cv.notify_one();

Do we essentially need the scoped_lock or any other lock here, if we are running the code on a processor which supports updates on byte-granularity. This essentially means that the assignment of bools are atomic which is typically the case with x86 processors.

Has it got something to do with syncing of the variable in the case when the two threads are running on two different processors and have separate caches?

回答1:

Yes you do, and using atomic is not sufficient.

CVs for efficiency can be woken spuriously, and those spurious lookups (or similar issues) can cause a write to be missed.

Imagine a spurious wake up. The recieving thread checks the bool, sees nothing (false), then is preempted. Someone notify all's and sets the bool. The notification is discarded, as the recieving thread is already processing one. The recieving thread now completes, and misses the message.

Now, add a lock in the sender that overlaps some time sequenced after the bool is set and before the cv notification. This communicaton hole no longer exists.

(Even without spurious wakeups, multiple notifications can cause similar problems sometimes.)

You do not have to hold the lock while notifying (and in fact this is a pessimization), but the lock must be held post-write and pre-notify for some period, in general.