3

我正在阅读有关 Condition 的信息java.util.concurrent.locks.Condition

条件将对象监视器方法(等待、通知和通知所有)分解为不同的对象,通过将它们与任意锁定实现的使用结合起来,使每个对象具有多个等待集的效果。

有人可以解释一下吗?

与普通同步块或方法相比,这有什么好处?

4

3 回答 3

15

一个锁可以与许多条件相关联。锁是一个“对象”,每个条件都是一个“等待集”。这允许独立条件共享临界区。例如,考虑有界生产者-消费者问题。解决它的一种方法是拥有一个保护队列的锁和两个独立的等待集:一个用于生产者,等待槽将项目放入队列,另一个用于等待项目获取的消费者。使用普通的旧APIsynchronizedwait/notifyAPI,我们能做的最好的就是遵循以下原则:

  • 生产商:

    synchronized (lock) {
        while (queue.isFull()) {
            lock.wait();
        }
        queue.put(sth);
        lock.notify();
    }
    
  • 消费者:

    synchronized (lock) {
        while (queue.isEmpty() {
            lock.wait();
        }
        product = queue.take();
        lock.notify();
    }
    

这样做的缺点是每次对队列进行更改时都会唤醒生产者和消费者,即使它不可能允许给定线程继续进行(例如,当其他消费者从队列中获取项目时消费者被唤醒)。使用 Lock/Condition API,我们可以实现分离等待消费者和生产者的解决方案,从而减少冗余唤醒和检查:

Lock lock = new ReentrantLock();
Condition hasPlace = lock.newCondition();
Condition hasItems = lock.newCondition();
  • 生产商:

    lock.lock();
    try {
        while (queue.isFull()) {
            hasPlace.await();
        }
        queue.put(sth);
        hasItems.signal();
    } finally {
        lock.unlock();
    }
    
  • 消费者:

    lock.lock();
    try {
        while (queue.isEmpty()) {
            hasItems.await();
        }
        product = queue.take();
        hasPlace.signal();
    } finally {
        lock.unlock();
    }
    

这样,消费者等待生产者生产一些项目(hasItems 条件),并在从队列中删除项目时通知生产者有一个空槽(hasPlace 条件)。这两个条件都与相同的临界区(锁定)相关联,因此我们保留了通常的排除和等待时释放锁的保证,同时获得了分离等待队列的能力。

于 2013-08-28T14:33:27.143 回答
1

以前在显式锁之前,我们使用对象wait()notify()方法使线程等待某些事件发生,然后使用触发它们,notify()并且该对象的互斥锁必须与调用这些方法的线程一起使用。

所以每个锁对象只有一个等待集。等待集是wait()存储调用对象的线程的集合(不是字面意思)。

但是使用使用单个锁的 Explicit Lock 框架,您可以为与同一锁相关的不同条件创建多个等待集。正如 Javadoc 中的示例也解释了同样的事实。

Multiple Conditions == Multiple Wait sets

 final Lock lock = new ReentrantLock(); //Single Lock
 final Condition notFull  = lock.newCondition(); //Multiple conditions
 final Condition notEmpty = lock.newCondition();

因此,在JavaDoc中的 Buffer 示例中,消费者线程将等待 Buffer 为 NOT EMPTY 的条件,而生产者线程将等待条件 NOT FULL。

于 2013-08-28T14:33:34.760 回答
0

例如,对于有界数据结构,您可以拥有条件“notEmpty”和“notFull”并等待它们。只是一个例子。看看这里的例子。

于 2013-08-28T14:32:45.957 回答