erPool is now locked sem.acquire(); // bufferPool is still locked result = (MyBuffer) bufferPool.removeElementAt (0); } return result; } public void returnBuffer (MyBuffer buf) { synchronized (bufferPool) { // bufferPool is now locked bufferPool.addElement (buf); } sem.release(); // bufferPool is still locked }
Given the above code, assume:
- The semaphore is initialized to the number of buffers in the pool.
- All buffers are unavailable (i.e., have been handed out).
- Thread A wants a buffer.
- Thread B is using one, but is almost finished with it.
Here's how the deadlock can occur:
- Thread A calls the getBuffer() method.
- Thread A enters the synchronized (bufferPool) block in getBuffer. As a result, Thread A acquires the Java monitor for the bufferPool object. Recall that only one thread can hold a given object's monitor at a time.
- Thread A calls sem.acquire(). Since there are no buffers available, the semaphore's value is 0, so Thread A goes to sleep while it is still holding the monitor lock on the bufferPool object.
- Thread B finishes with its buffer. It calls the returnBuffer() method.
- Within returnBuffer(), Thread B attempts to acquire the monitor lock for the bufferPool object--but Thread A is already holding that lock, so Thread B goes to sleep, waiting for Thread A to release the lock.
- Deadlock. Thread A is waiting for Thread B to release the semaphore. Thread B, in turn, is waiting for Thread A to release the lock on the bufferPool object.
This particular deadlock situation is easily avoided as shown:
private ArrayList bufferPool = ...; private Semaphore sem = new ObjectLockSemaphore (bufferPool.size()); public MyBuffer getBuffer() { MyBuffer result = null; sem.acquire(); synchronized (bufferPool) { result = (MyBuffer) bufferPool.removeElementAt (0); } return result; } public void returnBuffer (MyBuffer buf) { synchronized (bufferPool) { // bufferPool is now locked bufferPool.addElement (buf); } sem.release(); // bufferPool is still locked }
@version
$Revision$
@deprecated J2SE 5.0 now provides a
java.util.concurrent.Semaphore class
@author Copyright © 2004-2007 Brian M. Clapper