java中 await/signal/signalAll 和wait/notify/notifyAll的区别是什么

168 阅读2分钟

在 Java 中,await, signal, 和 signalAlljava.util.concurrent.locks.Condition 接口的方法,而 wait, notify, 和 notifyAllObject 类的方法。它们用于线程间的同步和通信,但工作原理和应用场景有所不同。

1. await, signal, 和 signalAll (使用 Condition)

这些方法是在使用 ReentrantLock 等显式锁时使用的。Condition 提供了更灵活的线程等待和通知机制。

代码示例:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionExample {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private boolean conditionMet = false;

    public void awaitCondition() throws InterruptedException {
        lock.lock();
        try {
            while (!conditionMet) {
                condition.await(); // 等待条件满足
            }
            // 条件满足后的处理逻辑
            System.out.println("Condition met!");
        } finally {
            lock.unlock();
        }
    }

    public void signalCondition() {
        lock.lock();
        try {
            conditionMet = true;
            condition.signal(); // 唤醒一个等待线程
        } finally {
            lock.unlock();
        }
    }

    public void signalAllConditions() {
        lock.lock();
        try {
            conditionMet = true;
            condition.signalAll(); // 唤醒所有等待线程
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ConditionExample example = new ConditionExample();

        Runnable waitTask = () -> {
            try {
                example.awaitCondition();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        Runnable signalTask = () -> {
            example.signalCondition();
        };

        new Thread(waitTask).start();
        new Thread(signalTask).start();
    }
}

2. wait, notify, 和 notifyAll (使用 Object)

这些方法是 Object 类的方法,用于在同步代码块中等待和通知线程。必须在同步的上下文中使用,即在 synchronized 块中。

代码示例:

public class WaitNotifyExample {
    private final Object lock = new Object();
    private boolean conditionMet = false;

    public void waitCondition() throws InterruptedException {
        synchronized (lock) {
            while (!conditionMet) {
                lock.wait(); // 等待条件满足
            }
            // 条件满足后的处理逻辑
            System.out.println("Condition met!");
        }
    }

    public void notifyCondition() {
        synchronized (lock) {
            conditionMet = true;
            lock.notify(); // 唤醒一个等待线程
        }
    }

    public void notifyAllConditions() {
        synchronized (lock) {
            conditionMet = true;
            lock.notifyAll(); // 唤醒所有等待线程
        }
    }

    public static void main(String[] args) {
        WaitNotifyExample example = new WaitNotifyExample();

        Runnable waitTask = () -> {
            try {
                example.waitCondition();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        Runnable notifyTask = () -> {
            example.notifyCondition();
        };

        new Thread(waitTask).start();
        new Thread(notifyTask).start();
    }
}

主要区别

  1. 锁的类型

    • Condition 方法 (await, signal, signalAll) 需要显式的 ReentrantLock 或其他 Lock 实现。
    • wait/notify/notifyAllObject 类的方法,使用内置的监视器锁。
  2. 灵活性

    • Condition 提供了更多的灵活性和功能,例如多个条件对象和更复杂的等待/通知逻辑。
    • wait/notify/notifyAll 适用于较简单的同步需求。
  3. 重入性

    • 使用 ReentrantLock 时,锁的重入性是显式管理的,而 synchronized 块内的锁具有内置的重入性。