问题
I am new to multi threading. While writing multi threaded code in C++11 using condition variable , I use the following construct
while(predicate) {
cond_var.wait(&lock);
}
However, I have been reading Deitel's third edition book on operating systems(chp 6) where the following construct is being used
if(predicate) {
cond_var.wait(&lock);
}
So, what's the difference? Why isn't the book using while? Isn't spurious call an issue?
回答1:
Spurious wakeup is always a potential issue. For example, look at the answers here: Do spurious wakeups actually happen?. Perhaps Deitel's code is part of a larger loop that can help them deal with the spurious wakeup? Or maybe it's just a typo.
In any case, there's never a (good) reason not to use your construct, and in fact the wait
function has a variant that does it for you (http://en.cppreference.com/w/cpp/thread/condition_variable/wait).
template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
which is equivalent to:
while (!pred()) {
wait(lock);
}
回答2:
People seem to be dealing with spurious wakeups exclusively, but there is a more fundamental reason why a while
or an if
is to be used in monitor procedures.
We would have to choose one or the other even if there were no spurious wakeups because monitor implementations may choose from a number of different signaling disciplines.
The following paper describes these
John H. Howard. 1976. Signaling in monitors. In Proceedings of the 2nd international conference on Software engineering (ICSE '76). IEEE Computer Society Press, Los Alamitos, CA, USA, 47-52.
The point is that a monitor can be used by at most one process at a time, and there is a conflict when a waiting process is being woken up (signaled) by another process from inside the monitor. The problem is: which process may continue executing inside the monitor?
There are a number of different disciplines. The one originally proposed is the so called signal and wait, where the signaled process continues immediately (the signaler has to wait). Using this discipline the
if ( predicate) {
cond_var.wait( &lock);
}
form can be used because the predicate must be true after waiting (provided it is true at the time of signaling)
Another discipline is signal and continue, where the signaling process continues, the signaled is put into an entry queue of the monitor. Using this discipline necessitates the use of the
while ( predicate) {
cond_var.wait( &lock);
}
form because predicate can be invalidated by the time the signaled process gets a chance to execute, so it has to retest the condition.
来源:https://stackoverflow.com/questions/22837254/predicate-for-condition-variable