`wait()` 和 `notify()` 方法要在同步块中调用的原因涉及到线程间的同步和协作机制,以及对象监视器锁的释放与获取。
1. 对象监视器锁:
在 Java 中,每个对象都有一个相关联的监视器锁(也称为内置锁或对象锁),它用于保护对象的同步访问。
要调用对象的 `wait()`、`notify()` 或 `notifyAll()` 方法,线程必须先获得该对象的监视器锁。
2. 同步块和监视器锁:
同步块(`synchronized` 块)允许线程获取对象的监视器锁,进入临界区,执行同步代码。
在同步块中调用 `wait()`、`notify()` 或 `notifyAll()` 方法可以确保线程在调用这些方法时已经持有了对象的监视器锁。
3. 等待和通知机制:
`wait()` 方法会释放当前线程持有的对象监视器锁,并使线程进入等待状态,直到其他线程调用相同对象的 `notify()` 或 `notifyAll()` 方法来唤醒它。
`notify()` 或 `notifyAll()` 方法会通知等待在对象上的线程,让它们进入对象的通知队列,等待竞争锁来继续执行。
因此,为了确保线程在调用 `wait()`、`notify()` 或 `notifyAll()` 方法时已经持有了对象的监视器锁,这些方法需要在使用 `synchronized` 同步块中调用。这样可以确保线程在等待和通知过程中,能够正确地获取和释放对象的监视器锁,避免出现并发问题和死锁。