wait、notify 和 notifyall 构成基于对象监视器的条件等待协议,必须在 synchronized 中调用以确保锁持有;wait 释放锁并进入等待队列,需用 while 循环防虚假唤醒;notify 随机唤醒一个线程,notifyall 唤醒全部,且仅对同一对象有效。

理解 wait、notify 和 notifyAll 的基础契约,关键不是记住“它们要配 synchronized”,而是明白:这三者共同构成 Java 中基于对象监视器(monitor)的**条件等待协议**——本质是一套线程间协商“什么时机该继续干活”的约定。
必须在同步上下文中调用
这不是语法限制,而是语义必需。因为:
-
wait() 会释放锁,所以调用前必须已持有该对象锁;否则无法释放,JVM 直接抛
IllegalMonitorStateException - notify()/notifyAll() 是“通知别人可以抢锁了”,只有当前持锁者才有资格发这个信号;没锁就发通知,等于乱喊“开饭了”,没人信,也不安全
- 实际写法只能是:
synchronized(obj) { ... obj.wait(); ... }或synchronized实例方法内调用this.wait()
wait() 不是 sleep,而是“条件不满足时让出锁+挂起”
它和 Thread.sleep() 完全不同:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
sleep(1000):线程自己睡 1 秒,锁不放,别人干等 -
wait():检查条件失败后,立刻释放当前对象锁,并进入该对象的**等待队列**,直到被唤醒或中断 - 务必配合 while 循环检查条件(不是 if),防止虚假唤醒或条件已变
notify 与 notifyAll 的语义差异决定安全性
唤醒行为不是“调度指令”,而是“广播信号”,后续是否能执行,取决于线程自己重新竞争锁 + 再次验证条件:
-
notify():随机唤醒等待队列中的一个线程;适合严格一对一协作(如双线程交替打印),但容易因唤醒错对象导致死锁 -
notifyAll():唤醒所有在该对象上 wait 的线程;推荐用于多数场景,尤其当多个线程等待不同条件(如队列“非空”和“未满”)时,由每个线程自己判断条件是否满足 - 没有“唤醒指定线程”的机制,也不能控制唤醒顺序
它们操作的是对象级别的等待队列,不是线程池或全局队列
每个 Java 对象都有自己的 monitor,也就有独立的等待队列:
-
obj1.wait()进入obj1的等待队列;obj2.notify()只影响obj2队列里的线程 - 不能跨对象通信:对 A 调用
wait(),却指望对 B 调用notify()来唤醒——完全无效 - 这是面向对象层面的协作原语,不是线程调度 API
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










