Java 如何通知其他监视器上等待的所有线程?

Java 如何通知其他监视器上等待的所有线程?,java,multithreading,concurrency,monitor,Java,Multithreading,Concurrency,Monitor,假设你有一个银行账户。您有两个同步的方法 public synchronized void withdraw ( int amount, String name ) { while ( account_balance < amount ) { try { wait(); } catch (InterruptedException e) { } } public synchronized void deposit (

假设你有一个银行账户。您有两个同步的方法

public synchronized void withdraw ( int amount, String name ) {
    while ( account_balance < amount ) {
        try {
            wait();
        } catch (InterruptedException e) {
    }

}

public synchronized void deposit ( int amount, String name ) {
     while ( account_balance > 3*amount ) {
        try {
            wait();
        } catch (InterruptedException e) {
        }
    }

}
public synchronized void draw(整数金额、字符串名称){
同时(账户余额<金额){
试一试{
等待();
}捕捉(中断异常e){
}
}
公共同步作废存款(整数金额,字符串名称){
同时(账户余额>3*金额){
试一试{
等待();
}捕捉(中断异常e){
}
}
}

在提款监视器中等待的线程正在等待另一个线程存款,以便它们可以提款,反之亦然。因此,如果一个线程提款,通知提款监视器中的所有线程没有意义,通知在存款监视器中等待的线程是有意义的,因为帐户余额“已满”反之亦然。由于无法指定哪个线程使用notify()唤醒,notifyAll()通知正在当前监视器中等待的线程,如何通知正在其他监视器上等待的线程?

使用java.util.concurrent.locks.ReentrantLock而不是使用该语言的内置监视器如何

class Account {
    private final Lock lock = new ReentrantLock();
    private final Condition depositOk = lock.newCondition();
    private final Condition withdrawOk = lock.newCondition();

    public void withdraw(amount) {
        lock.lock();
        try {
            while (!accountContainsAtLeast(amount)) {
                withdrawOk.await();
            }
            withdrawLocked(amount);
            depositOK.signal();
        } finally {
            lock.unlock();
        }
    }

    public void deposit(amount) {
        lock.lock();
        try {
            while (!OKtoDeposit(amount)) {
                depositOk.await();
            }
            depositLocked(amount);
            withdrawOK.signal();
        } finally {
            lock.unlock();
        }
    }
}
notifyAll()通知当前监视器中等待的线程


不,不会。它会通知所有等待监视器的线程你调用它。这正是你想要的。

为什么不在另一个对象上同步?使用新并发API中的。你需要在调用这些方法的对象上调用
notifyAll()
。@Larper想要存款()只唤醒正在Draw()中等待的线程,反之亦然。不想让deposit()唤醒其他储户或Draw()唤醒其他取款人。@jameslarge如果这是问题的话,两个监视器可以解决它,这就是为什么他问“其他监视器”。@Larper,使用两个监视器听起来可能是一个解决方案,但我不确定你是否真的可以在不冒“丢失”风险的情况下让它工作通知。另外,别忘了,你需要一个互斥锁来防止线程看到帐户处于不一致的状态。尝试处理三个监视器会变得很难看。java.util.concurrent包中的锁对象(参见我的答案)允许任意数量的独立条件与一个互斥体相关联,这很好地解决了您的问题。我被教导在while循环中使用try块,但您却使用了相反的方法。有什么区别?您认为什么更好?@Larper,您是否应该在循环中处理异常是一个完全不同的主题,答案将取决于设计选择和应用程序的需要。不过,在这种情况下,try块根本不处理异常。在我的示例中,try块的目的是确保,无论发生什么情况,互斥锁都将在方法返回之前解锁。