Domanda

Inside the documentation for the Condition interface: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html

there is an example class which uses the condition. I will copy/paste here:

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();
     }
   }
 }

What I do not understand is how this can possibly work (note: I did not test it, I just assume that it works) without creating a deadlock?

If I call BoundedBuffer.put a hundred times then on the hundredth time it will be blocked in the notFull.await() method and this will be under a lock. If I then do BoundedBuffer.take() from another thread then I should be blocked on the first line in the lock.lock().

Am I missing something here?

È stato utile?

Soluzione

Yes you do miss something. From the JavaDoc:

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.wait.

Hence, the lock is released when await() is called.

From the JavaDoc of the await() method itself:

void await() throws InterruptedException

Causes the current thread to wait until it is signalled or interrupted. 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:

And the method signal() awakes a thread which will re-acquire the lock before continuing. From the JavaDoc of the method signal():

void signal()

Wakes up one waiting thread. If any threads are waiting on this condition then one is selected for waking up. That thread must then re-acquire the lock before returning from await.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top