必须在 synchronized 块中调用 wait/notify,否则抛 IllegalMonitorStateException;推荐优先使用 BlockingQueue 或 Condition 替代手写 wait/notify。

wait/notify 必须在 synchronized 块中调用
直接调用 wait() 或 notify() 会抛出 IllegalMonitorStateException,因为这两个方法依赖当前线程持有对象的监视器锁。JVM 要求调用前必须已通过 synchronized 获取该对象锁。
- 错误写法:
obj.wait();(未加锁)→ 立即崩溃 - 正确写法:
synchronized(obj) { obj.wait(); } -
wait()会释放锁并挂起线程;notify()不释放锁,只唤醒一个等待线程 - 用
notifyAll()更安全,避免因条件判断不一致导致的“假死”(如多个生产者/消费者共用同一锁)
用 Condition 替代 wait/notify 实现更清晰的等待队列
Condition 是 java.util.concurrent.locks 包提供的替代方案,配合 ReentrantLock 使用,能为不同等待逻辑创建独立的等待队列,避免 notify() 唤醒错类型线程的问题。
- 一个
ReentrantLock可关联多个Condition:比如notFull和notEmpty -
condition.await()类似wait(),但需在lock.lock()/lock.unlock()块内 - 唤醒指定队列:
notFull.signal()不会影响notEmpty上等待的线程 - 注意:不能混用
synchronized+Condition,否则抛IllegalMonitorStateException
volatile 不足以实现线程间通信,仅适合简单状态通知
volatile 能保证变量读写的可见性与有序性,但无法保证原子性。它适用于「一个线程改、多个线程读」的轻量级信号场景(如开关标志),但不能替代同步机制来协调共享资源访问。
- 适用:
private volatile boolean shutdownRequested = false;,配合循环检查 - 不适用:计数器
counter++—— 该操作包含读-改-写三步,volatile无法阻止竞态 - 若需原子更新,改用
AtomicInteger或加锁;若需等待条件成立,仍得靠wait/notify或Condition
BlockingQueue 是最实用的线程间通信抽象
对于典型的生产者-消费者模型,直接使用 BlockingQueue(如 ArrayBlockingQueue、LinkedBlockingQueue)比手写 wait/notify 更可靠、简洁,且内置了线程安全和阻塞语义。
立即学习“Java免费学习笔记(深入)”;
-
queue.put(item)在队列满时自动阻塞,queue.take()在空时自动阻塞 - 所有操作线程安全,无需额外同步;容量可选(有界 vs 无界),影响背压行为
- 避免手动管理锁、条件变量、中断响应等细节,减少出错概率
- 注意:
offer(item, timeout, unit)和poll(timeout, unit)支持超时,适合需要响应中断或避免永久阻塞的场景
BlockingQueue 或 Phaser、Exchanger 这类高级工具,真卡在性能或语义限制上,再深入 Condition 或 LockSupport。










