为什么wait和notify方法要在同步块中调用?

1 个回答

  • 朱八戒
    你要习惯任何人的忽冷忽然,也要看淡任何人的渐行渐远。
    在 Java 中,`wait()`, `notify()`, 和 `notifyAll()` 方法必须在同步块或同步方法中调用。以下是详细的原因和解释: #### 1. 确保调用线程拥有对象的独占锁 只有在调用线程拥有某个对象的独占锁时,才能调用该对象的 `wait()`, `notify()`, 和 `notifyAll()` 方法。如果不这么做,代码会抛出 `IllegalMonitorStateException` 异常。 ```java synchronized (object) { object.wait(); } synchronized (object) { object.notify(); } ``` #### 2. 避免竞态条件 在同步块中调用 `wait()` 和 `notify()` 方法是为了避免竞态条件。竞态条件是指两个或多个线程在操作共享资源时,由于执行顺序的不确定性,可能导致程序的错误行为。 #### 3. `wait()` 方法释放锁并等待通知 - `wait()` 方法强制当前线程释放对象锁,并使线程进入等待状态。 - 在调用某对象的 `wait()` 方法之前,当前线程必须已经获得该对象的锁。因此,线程必须在某个对象的同步方法或同步代码块中才能调用该对象的 `wait()` 方法。 ```java synchronized (object) { object.wait(); } ``` #### 4. `notify()` 和 `notifyAll()` 方法通知等待的线程 - 在调用对象的 `notify()` 和 `notifyAll()` 方法之前,调用线程必须已经获得该对象的锁。 - 因此,必须在某个对象的同步方法或同步代码块中才能调用该对象的 `notify()` 或 `notifyAll()` 方法。 ```java synchronized (object) { object.notify(); } ``` #### 5. 线程间通信的机制 调用 `wait()` 方法的原因通常是,调用线程希望某个特殊的状态(或变量)被设置之后再继续执行。调用 `notify()` 或 `notifyAll()` 方法的原因通常是,调用线程希望告诉其他等待中的线程:"特殊状态已经被设置"。 这个状态作为线程间通信的通道,必须是一个可变的共享状态(或变量)。 ### 示例代码 以下是一个简单的示例,演示了 `wait()` 和 `notify()` 方法在同步块中的使用: ```java class SharedResource { private boolean condition = false; public synchronized void waitForCondition() { while (!condition) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Condition met, proceeding..."); } public synchronized void setConditionAndNotify() { condition = true; notify(); } } public class WaitNotifyExample { public static void main(String[] args) { SharedResource sharedResource = new SharedResource(); Thread waitingThread = new Thread(() -> { sharedResource.waitForCondition(); }); Thread notifyingThread = new Thread(() -> { try { Thread.sleep(1000); // Simulate some work sharedResource.setConditionAndNotify(); } catch (InterruptedException e) { e.printStackTrace(); } }); waitingThread.start(); notifyingThread.start(); } } ``` ### 关键点总结 - **同步块的必要性**:`wait()`, `notify()`, 和 `notifyAll()` 方法必须在同步块或同步方法中调用,以确保调用线程拥有对象的独占锁。 - **避免竞态条件**:在同步块中调用这些方法可以避免竞态条件,确保线程间通信的正确性。 - **线程通信**:`wait()` 方法用于等待特定条件,`notify()` 和 `notifyAll()` 方法用于通知等待的线程条件已满足。 通过这些机制,Java 提供了一种安全和有效的线程间通信方式。
    发布于 2024-07-23 14:09 •IP属地 安徽
    举报
    评论
    收藏