wait/notify 和 singal有什么区别
·
wait/notify 和 Condition.signal() 本质上都是线程间通信机制,但它们属于不同层次的 API。
| 对比项 | wait/notify | Condition.signal |
|---|---|---|
| 所属类 | Object | Condition |
| 配套锁 | synchronized | ReentrantLock |
| JDK版本 | Java 1.0 | Java 5 |
| 等待方法 | wait() | await() |
| 唤醒方法 | notify()/notifyAll() | signal()/signalAll() |
| 灵活性 | 较低 | 较高 |
| 支持多个等待队列 | 不支持 | 支持 |
| 可中断等待 | 支持 | 支持 |
| 超时等待 | 支持 | 支持 |
1. wait/notify
必须配合 synchronized 使用。
示例
class Message {
private boolean ready = false;
public synchronized void get() throws Exception {
while (!ready) {
wait();
}
System.out.println("收到消息");
}
public synchronized void send() {
ready = true;
notify();
}
}
执行流程:
线程A
↓
wait()
↓
进入 Object 的 WaitSet
线程B
↓
notify()
↓
唤醒A
wait 的本质
调用:
wait();
会做两件事:
1. 释放 synchronized 锁
2. 进入等待队列
被唤醒后:
重新竞争锁
获得锁后继续执行
2. Condition.await/signal
Condition 是 JUC 包提供的高级版本。
必须配合:
ReentrantLock
使用。
示例
class Message {
private final ReentrantLock lock =
new ReentrantLock();
private final Condition condition =
lock.newCondition();
private boolean ready = false;
public void get() throws Exception {
lock.lock();
try {
while (!ready) {
condition.await();
}
System.out.println("收到消息");
} finally {
lock.unlock();
}
}
public void send() {
lock.lock();
try {
ready = true;
condition.signal();
} finally {
lock.unlock();
}
}
}
3. 最大区别:多个等待队列
这是面试最喜欢问的点。
wait/notify
只有一个等待队列。
synchronized(lock){
wait();
}
所有线程都在同一个队列:
WaitSet
线程A
线程B
线程C
线程D
调用:
notify();
JVM随机唤醒一个。
Condition
可以创建多个 Condition。
Lock lock = new ReentrantLock();
Condition notEmpty = lock.newCondition();
Condition notFull = lock.newCondition();
队列变成:
notEmpty队列
消费者1
消费者2
notFull队列
生产者1
生产者2
可以精准唤醒:
notEmpty.signal();
只唤醒消费者。
notFull.signal();
只唤醒生产者。
4. 生产者消费者案例
wait/notify
notifyAll();
必须全部唤醒:
生产者醒了
消费者醒了
生产者又睡了
大量无效唤醒。
Condition
notEmpty.signal();
只唤醒消费者。
notFull.signal();
只唤醒生产者。
效率更高。
5. 底层关系
很多人以为 Condition 完全是新东西,其实不是。
JDK 的实现思路:
ObjectMonitor
↓
wait/notify
升级为:
AQS
↓
ConditionObject
↓
await/signal
Condition 本质上是 AQS 维护的条件队列。
6. signal 和 notify 的对应关系
wait() <=> await()
notify() <=> signal()
notifyAll() <=> signalAll()
面试总结
如果面试官问:
Condition.signal() 和 Object.notify() 有什么区别?
可以直接回答:
notify()必须配合synchronized,signal()必须配合ReentrantLock。wait/notify只有一个等待队列,而Condition可以创建多个条件队列。signal()可以精准唤醒指定队列中的线程,避免notifyAll()带来的无效唤醒。Condition基于 AQS 实现,功能更强,是 JUC 对wait/notify的增强版。- 在现代并发编程中,除了简单场景,通常优先使用
Lock + Condition而不是synchronized +
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)