java中wait、notify、notifyall是object类提供的线程协作方法,必须在synchronized块中调用,分别实现线程等待、随机唤醒一个线程、唤醒所有等待线程,且需配合while循环、状态更新后通知、同一锁对象使用以确保正确性。

Java 中 wait、notify 和 notifyAll 是 Object 类提供的原生线程协作方法,它们必须在同步上下文(即 synchronized 块或方法)中调用,用于实现线程间的等待与唤醒机制。核心在于:它们操作的是对象的“内置锁(monitor)”和与之关联的“等待队列”,而非线程本身。
wait 会让当前线程释放锁并进入等待状态
wait() 的本质是:当前持有对象锁的线程主动放弃锁,并被挂起,加入该对象的等待队列。它不会自动醒来,必须依赖其他线程对该对象调用 notify() 或 notifyAll() 才可能被唤醒。
- 必须在
synchronized(obj)内调用,否则抛IllegalMonitorStateException - 调用后立即释放
obj的锁,其他线程才能获取并执行同步代码 - 被唤醒后,线程不会立刻继续执行,而是重新竞争该对象的锁;获得锁后才从
wait()返回 - 推荐始终在
while循环中使用wait(),防止虚假唤醒(spurious wakeup)或条件已失效
notify 随机唤醒一个等待中的线程
notify() 从对象的等待队列中随机选择一个线程将其唤醒。被唤醒的线程仍需重新竞争锁,只有抢到锁后才能继续运行。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 同样必须在
synchronized(obj)内调用 - 不保证唤醒哪个线程,也不保证唤醒时机——仅表示“可能可以继续了”
- 适用于明确知道只需唤醒一个消费者/生产者等场景(如单缓冲区生产者-消费者)
- 若等待队列为空,
notify()无效果,不报错
notifyAll 唤醒所有等待线程,由它们竞争锁和条件判断
notifyAll() 将对象等待队列中所有线程全部唤醒。它们会一起竞争对象锁,获得锁后各自检查业务条件是否满足,再决定是否继续执行或再次 wait()。
- 更安全,避免因唤醒遗漏导致死锁(例如多个条件共用同一把锁时)
- 典型适用场景:多个不同等待条件共享同一个锁(如读写锁模拟、多条件等待)
- 性能略低于
notify()(唤醒多线程 + 多次条件重判),但逻辑更健壮 - 即使只有一个线程在等待,也建议优先考虑
notifyAll()以提升可维护性
正确使用的三个关键点
这三个方法容易误用,导致死锁、丢失通知或虚假唤醒。务必注意:
- 永远在 while 循环中调用 wait():不能用 if,因为唤醒后条件可能已变(如其他线程抢先处理)
- notify/notifyAll 必须在修改完共享状态后调用:确保唤醒的线程看到最新数据
- wait 和 notify/notifyAll 必须作用于同一个对象实例:锁对象要一致,否则形同虚设
不复杂但容易忽略细节。用对了,就是轻量高效的线程协作;用错了,就变成难以复现的并发 bug。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










