Java Reference
In-Depth Information
so that they can remain constant while the precondition is tested. But if the precondition does
not hold, the lock must be released so another thread can modify the object state—otherwise
the precondition will never become true. The lock must then be reacquired before testing the
precondition again.
Listing 14.1. Structure of Blocking State-dependent Actions.
Bounded buffers such as ArrayBlockingQueue are commonly used in producer-con-
sumer designs. A bounded buffer provides put and take operations, each of which has pre-
conditions: you cannot take an element from an empty buffer, nor put an element into a full
buffer. State dependent operations can deal with precondition failure by throwing an excep-
tion or returning an error status (making it the caller's problem), or by blocking until the ob-
ject transitions to the right state.
We're going to develop several implementations of a bounded buffer that take different ap-
proaches to handling precondition failure. Each extends BaseBoundedBuffer in Listing
14.2 , which implements a classic array-based circular buffer where the buffer state variables
( buf , head , tail , and count ) are guarded by the buffer's intrinsic lock. It provides syn-
chronized doPut and doTake methods that are used by subclasses to implement the put
and take operations; the underlying state is hidden from the subclasses.
14.1.1. Example: Propagating Precondition Failure to Callers
GrumpyBoundedBuffer in Listing 14.3 is a crude first attempt at implementing a
bounded buffer. The put and take methods are synchronized to ensure exclusive ac-
cess to the buffer state, since both employ check-then-act logic in accessing the buffer.
Search WWH ::




Custom Search