在Condition接口的文档中:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html

有一个使用条件的示例类。我将在此处复制/粘贴:

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


我不明白的是,如何在不产生死锁的情况下可以工作(注意:我没有测试它,我只是假设它可以工作)?

如果我调用BoundedBuffer.put一百次,则在第100次它将在notFull.await()方法中阻塞,并且将处于锁定状态。
如果然后从另一个线程执行BoundedBuffer.take(),则应该在lock.lock()的第一行上将我阻止。

我在这里想念什么吗?

最佳答案

是的,您确实会错过某些事情。从JavaDoc


  等待条件提供的关键属性是,它自动释放关联的锁并挂起当前线程,就像Object.wait一样。


因此,在调用await()时释放锁定。

await()方法本身的JavaDoc中:


  void await()抛出InterruptedException
  
  使当前线程等待,直到发出信号或被中断为止。与此条件相关联的锁被原子释放,并且出于线程调度目的,当前线程被禁用,并且处于休眠状态,直到发生以下四种情况之一:


方法signal()唤醒一个线程,该线程将在继续操作之前重新获取该锁。从方法signal()的JavaDoc中:


  无效signal()
  
  唤醒一个等待线程。如果有任何线程在这种情况下等待,则选择一个线程进行唤醒。然后,该线程必须重新获取锁,然后才能从等待返回。

07-25 21:25
查看更多