【问题标题】:How do java.util.concurrent.locks.Condition work?java.util.concurrent.locks.Condition 是如何工作的?
【发布时间】:2025-12-15 17:40:02
【问题描述】:

阅读关于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() 现在满足条件,如果等待缓冲区未满的线程尚未释放锁,则释放锁

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

谢谢。

【问题讨论】:

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


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

    【讨论】: