notify():隨機喚醒單一在該物件監視器上
wait()的執行緒。
notifyAll():喚醒所有在該物件監視器上wait()的執行緒。
關鍵點:被喚醒的執行緒不會立即執行,必須重新競爭鎖(monitor),只有拿到鎖的執行緒才能從wait()返回繼續執行。
經典「生產者-消費者」缓衝區模型示範:
public synchronized void put(Object o) {
while (buf.size() == MAX_SIZE) wait(); // 滿了等待
buf.add(o);
notify(); // 唤醒一个等待者
}
public synchronized Object get() {
while (buf.size() == 0) wait(); // 空了等待
Object o = buf.remove(0);
notify(); // 唤醒一个等待者
return o;
}
wait() 釋放鎖並進入等待集get(),移除一個元素,呼叫 notify()notify() 隨機喚醒另一個消費者 C2(而非生產者 P1)notify()若改用 notifyAll(),P1 會被喚醒並有機會競爭鎖,系統恢復平衡。
notifyAll() 的效能開銷微乎其微(現代 JVM 優化極好)java.util.concurrent 高階組件(Condition、BlockingQueue、Semaphore),完全避開 wait/notify 陷阱Lock lock = new ReentrantLock();
Condition notFull = lock.newCondition(); // 生產者等待
Condition notEmpty = lock.newCondition(); // 消費者等待
public void put(Object o) {
lock.lock();
try {
while (buf.size() == MAX_SIZE) notFull.await();
buf.add(o);
notEmpty.signal(); // 精確喚醒消費者
} finally { lock.unlock(); }
}
public Object get() {
lock.lock();
try {
while (buf.isEmpty()) notEmpty.await();
Object o = buf.remove(0);
notFull.signal(); // 精確喚醒生產者
return o;
} finally { lock.unlock(); }
}
Condition 將單一物件的等待集拆分為多個邏輯等待隊列,實現「該喚醒誰、喚醒誰」,徹底解決 notify() 的盲目喚醒問題。
ObjectMonitor::notify() vs ObjectMonitor::notifyAll() 實作差異除非你是 JVM 核心庫開發者,否則請忘掉 notify(),永遠使用 notifyAll() 或更高階的 Condition/BlockingQueue。