Let's say you have a bank account. You have two synchronized methods
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) {
}
}
}
Threads that wait in withdraw monitor are waiting for another thread to deposit some money so they can withdraw and vice versa. So it makes no sense notifying all threads in withdraw monitor if one thread withdraws money, it makes sense to notify threads that are waiting in deposit monitor cause account balance is "full" and vice versa. Since you can't specify which thread wakes up with notify() and notifyAll() notifies threads waiting in the current monitor how does one notify threads that are waiting on some other monitor?
How about using java.util.concurrent.locks.ReentrantLock instead of using the language's built-in monitors?
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();
}
}
}