Java Reference
In-Depth Information
change for a while. On the other hand, if the caller decides to sleep so as not to consume so
much CPU time, it could easily “oversleep” if the buffer state changes shortly after the call
to sleep . So the client code is left with the choice between the poor CPU usage of spin-
ning and the poor responsiveness of sleeping. (Somewhere between busy waiting and sleep-
ing would be calling Thread.yield in each iteration, which is a hint to the scheduler that
this would be a reasonable time to let another thread run. If you are waiting for another thread
to do something, that something might happen faster if you yield the processor rather than
consuming your full scheduling quantum.)
14.1.2. Example: Crude Blocking by Polling and Sleeping
SleepyBoundedBuffer in Listing 14.5 attempts to spare callers the inconvenience of
implementing the retry logic on each call by encapsulating the same crude “poll and sleep”
retry mechanism within the put and take operations. If the buffer is empty, take sleeps
until another thread puts some data into the buffer; if the buffer is full, put sleeps until an-
other thread makes room by removing some data. This approach encapsulates precondition
management and simplifies using the buffer—definitely a step in the right direction.
The implementation of SleepyBoundedBuffer is more complicated than the previous
attempt. [3] The buffer code must test the appropriate state condition with the buffer lock held,
because the variables that represent the state condition are guarded by the buffer lock. If the
test fails, the executing thread sleeps for a while, first releasing the lock so other threads can
access the buffer. [4] Once the thread wakes up, it reacquires the lock and tries again, alternat-
ing between sleeping and testing the state condition until the operation can proceed.
From the perspective of the caller, this works nicely—if the operation can proceed immedi-
ately, it does, and otherwise it blocks—and the caller need not deal with the mechanics of
failure and retry. Choosing the sleep granularity is a tradeoff between responsiveness and
CPU usage; the smaller the sleep granularity, the more responsive, but also the more CPU re-
sources consumed. Figure 14.1 shows how sleep granularity can affect responsiveness: there
may be a delay between when buffer space becomes available and when the thread wakes up
and checks again.
Search WWH ::




Custom Search