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

时间:2016-04-05 19:49:49

标签: java multithreading concurrency locking java.util.concurrent

阅读有关java.util.concurrent.locks.Condition接口的Java 8文档,给出了以下示例:

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()现在满足条件,如果线程没有释放锁等待缓冲区未满,则释放锁
  4. 这些是初学者的问题。请帮帮我。

    谢谢。

1 个答案:

答案 0 :(得分:2)

  1. 是的,这是正确的,一旦等待条件,它就会释放锁定。 await/signal/signalAll实际上与wait/notify/notifyAll
  2. 具有相同的行为
  3. 没有ReentrantLock是一个独占锁,所以只有一个线程可以获得锁。
  4. 见#1。当线程调用signalsignalAll时,它分别释放一个线程或等待相应Condition的所有线程,以使线程或那些线程有资格再次获取锁。但是现在锁仍然由调用signalsignalAll的线程拥有,直到它通过调用lock.unlock显式释放锁。然后已经释放的线程将能够尝试再次获取锁定,可以获取锁定的线程将能够再次检查该条件(这次我的意思是条件count == items.length或者在此示例中为count == 0,如果没有问题,它将继续,否则它将再次await并释放锁定以使其可用于另一个线程。