Information Technology Reference
In-Depth Information
what the predicate should be. In this situation, we often find it useful to name
a private method function that will perform the test (e.g., workAvailable()
in the above example) and write the code that defines the details for that test
later.
5.6.6
Signal() and Broadcast() calls
Just as you must decide when methods can wait, you must decide when methods
can let other waiting threads proceed. It is usually easy to ask \Can a call to
this method allow another thread to proceed?" and then add a Signal() or
Broadcast() call if the answer is yes. But which call should you use?
Signal() is appropriate when (1) at most one waiting thread can make
progress and (2) any thread waiting on the condition variable can make progress.
In contrast, Broadcast() is needed when (1) multiple waiting threads may all
be able to make progress or (2) different threads are using the same condition
variable to wait for different predicates, so some of the waiting threads can make
progress but others can't.
Example: Resource Manager. As an example of the latter case, sup-
pose that we use a single condition variable the n-resource ResourceManager
sketched above. Whenever a resource is freed, we must broadcast() on the
condition variable: we don't know which thread(s) can make progress, so we
tell them all to check. If, instead, we just signalled, then the “wrong” thread
might receive the signal, and a thread that could make progress might remain
blocked.
It is always safe to use Broadcast() . Even in cases where signal would
suce, at worst all of the waiting threads would run and check the condition
in the while loop, but only one would continue out of the loop. Compared
to signal() , such a case consumes some additional resources, but would not
introduce any bugs.
Double Checked Locking
The body of the text advises holding a shared object's lock across any method that
accesses the object's member variables. Programmers are often tempted to avoid some
of these lock acquire and release operations. Unfortunately, such efforts often result in
code that is complex, wrong, or both.
To illustrate the challenges, consider the double checked locking design pattern.
The canonical example 6 is for an object Singleton that provides access to an object
that is allocated lazily the first time it is needed by any thread.
6 The example and analysis is taken from Meyers and Alexandrescu's \C++ and the Perils
of Double-Checked Locking"
 
Search WWH ::




Custom Search