The following code is taken from the JavaDoc of Condition:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
Imagine 2 threads, Consumer and Producer, one using take, one put on a single instance of BoundedBuffer.
Let’s say Consumer goes first, runs take() in which he locks the lock and now loops on notEmpty.await();.
How can now Producer possibly get into the put() method past locking the lock, which is already held by the Consumer?
What am I missing here? Is the lock “temporarily released” while the thread is waiting on one of its conditions? And what does the reentrancy of the lock mean, exactly?
Both
Lockandsynchronizedallow a thread to give up the lock when waiting and another thread can obtain the lock. To stop waiting, a thread have to re-acquire the lock.Note: They don’t release it fully and if you take a stack trace you can have multiple threads which appear to be holding the lock at once, but at most one of them will be running (the rest will be blocking)
From Condition.await()