Information Technology Reference
In-Depth Information
E.g., the pattern is always
while(predicateOnStateVariables(...))){
condition->Wait(&lock);
}
never
if(predicateOnStateVariables(...))){
condition->Wait(&lock);
}
Here,
predicateOnStateVariables(...)
is code that looks at the state
variables of the current object to decide if it is OK to proceed.
One is sometimes tempted to guard a
wait()
call with an
if
conditional
rather than a
while
loop when one knows exactly what threads are taking
what actions and one can deduce from the global structure of the program
that despite Hansen semantics, any time a thread returns from
wait()
, it
can proceed. Avoid this temptation.
While
works any time
if
does, and it works in situations when
if
doesn't.
By the principle of consistent structure, you should do things the same
way every time. But there are three additional issues.
First,
if
breaks modularity. In the example sketched above, one needs
to consider the global structure of the program|what threads are there,
where is
signal()
called, etc|to determine whether
if
will work. The
problem is that a change in code in one method (say, adding a
signal()
)
can then cause a bug in another method (where the
wait()
is).
While
code is also self-documenting|one can look at the
wait()
and see exactly
when a thread may proceed.
Second, when you always use
while
, you are given incredible freedom
about where you put the
signals()
. In fact,
signal()
becomes a hint|
you can add more signals to a correct program in arbitrary places and it
remains a correct program.
Third,
if
breaks portability. Some implementations of condition variables
may allow spurious wakeups, where
wait()
returns even though no thread
called
signal()
or
broadcast()
. For example, implementations of con-
dition variables in both Java and the Posix pthreads library are allowed
to have spurious wakeups.
5. (Almost) never
sleep()
.
Many threads libraries have a
sleep()
function that suspends execution
of the calling thread for some period of wall clock time. Once that time
passes, the thread is returned to the scheduler's ready queue and can run
again.
Never use
sleep()
to have one thread wait for another thread to do some-
thing. The correct way to wait for a condition to become true is to
wait()
on a condition variable.