Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting on a condition in a reentrant lock

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?

like image 512
vektor Avatar asked Sep 25 '12 08:09

vektor


People also ask

Does condition await release lock?

The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.

Why must a thread be holding a lock to wait on a condition variable?

You must hold the lock to prevent another thread from racing with your wait. Show activity on this post. Well, even with a “naked wait”, we have the problem that the wait will only return if another thread calls notify after the wait has started.

What is correct about reentrant lock?

A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when the lock is not owned by another thread. The method will return immediately if the current thread already owns the lock.

Why is ReentrantLock called reentrant?

As the name says, ReentrantLock allows threads to enter into the lock on a resource more than once. When the thread first enters into the lock, a hold count is set to one. Before unlocking the thread can re-enter into lock again and every time hold count is incremented by one.


2 Answers

Both Lock and synchronized allow 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()

The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
  • Some other thread invokes the signalAll() method for this Condition; or
  • Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
  • A "spurious wakeup" occurs.

In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. When the thread returns it is guaranteed to hold this lock

like image 175
Peter Lawrey Avatar answered Oct 02 '22 23:10

Peter Lawrey


As far as re-entrancy, this means that a thread that holds a certain lock can re-acquire the same lock again. If this wasn't so, a synchronized method would not be able to call another synchronized method of the same object.

Re-entrancy is not involved in the understanding of your problem.

like image 43
Marko Topolnik Avatar answered Oct 02 '22 22:10

Marko Topolnik