wait/notifyCondition.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() 有什么区别?

可以直接回答:

  1. notify() 必须配合 synchronizedsignal() 必须配合 ReentrantLock
  2. wait/notify 只有一个等待队列,而 Condition 可以创建多个条件队列。
  3. signal() 可以精准唤醒指定队列中的线程,避免 notifyAll() 带来的无效唤醒。
  4. Condition 基于 AQS 实现,功能更强,是 JUC 对 wait/notify 的增强版。
  5. 在现代并发编程中,除了简单场景,通常优先使用 Lock + Condition 而不是 synchronized +
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐