java.util.concurrent.locks.Condition是如何工作的?

12

阅读Java 8文档关于java.util.concurrent.locks.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();
     }
   }
 }

所以我的主要问题是:条件是如何工作的?

  1. 当它开始等待时,它会释放锁吗?(例如notFull.await())?
  2. 不同的线程可以获取相同的锁并移动,直到它signal()一个条件,唤醒其他线程吗?
  3. 我认为这个例子会导致死锁,因为如果一个线程正在等待缓冲区不为空,并且它尚未释放锁,则另一个线程如何获取锁,清空缓冲区,signal()条件现在已满足,并通过如果等待缓冲区非空的线程尚未释放锁来释放锁?

这些都是初学者的问题。请帮帮我。

谢谢。

1个回答

13
  1. 是的,一旦等待条件,await/signal/signalAll 会释放锁。实际上,它们的行为与 wait/notify/notifyAll 相同。
  2. 不,ReentrantLock 是一种独占锁,因此只有一个线程可以获取该锁。
  3. 参见#1。当一个线程调用 signalsignalAll 时,它将分别释放一个线程或所有等待相应 Condition 的线程,以便这些线程将能够再次获取锁。但此时锁仍由调用 signalsignalAll 的线程所拥有,直到它通过调用 lock.unlock 显式地释放锁为止。然后已经被释放的线程将能够尝试再次获取锁,能够获取锁的线程将能够再次检查条件(这里的条件是指在本例中的 count == items.lengthcount == 0),如果条件满足,则继续进行,否则它将再次 await 并释放锁,以使其可供另一个线程使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接