gpt4 book ai didi

java - 为什么必须 wait() 始终处于同步块(synchronized block)中

转载 作者:bug小助手 更新时间:2023-10-28 10:40:03 25 4
gpt4 key购买 nike

我们都知道为了调用 Object.wait() ,此调用必须放在同步块(synchronized block)中,否则为 IllegalMonitorStateException被抛出。但是做这个限制的原因是什么?我知道wait()释放了监视器,但是为什么我们需要通过使特定 block 同步然后显式获取监视器通过调用 wait() 释放监视器?

如果可以在同步块(synchronized block)之外调用 wait() 并保留它的语义 - 挂起调用者线程,那么潜在的损害是什么?

最佳答案

What is the potential damage if it was possible to invoke wait() outside a synchronized block, retaining it's semantics - suspending the caller thread?

让我们用一个具体示例来说明如果 wait() 可以在同步块(synchronized block)之外调用我们会遇到什么问题。

假设我们要实现一个阻塞队列(我知道,API 中已经有一个:)

第一次尝试(没有同步)可能看起来像下面的几行

class BlockingQueue {
Queue<String> buffer = new LinkedList<String>();

public void give(String data) {
buffer.add(data);
notify(); // Since someone may be waiting in take!
}

public String take() throws InterruptedException {
while (buffer.isEmpty()) // don't use "if" due to spurious wakeups.
wait();
return buffer.remove();
}
}

这是可能发生的情况:

  1. 消费者线程调用 take() 并看到 buffer.isEmpty()

  2. 在消费者线程继续调用wait()之前,生产者线程出现并调用完整的give(),即buffer.add(数据);通知();

  3. 消费者线程现在将调用wait()(并且miss刚刚调用的notify())。

  4. 如果运气不好,生产者线程将不会产生更多的 give(),因为消费者线程永远不会唤醒,并且我们有一个死锁。

一旦你理解了这个问题,解决方案就很明显了:使用 synchronized 确保 notifyisEmpty 之间永远不会被调用等待

无需赘述:这个同步问题是普遍存在的。正如 Michael Borgwardt 所指出的,等待/通知完全是关于线程之间的通信,所以你总是会遇到类似于上面描述的竞争条件。这就是强制执行“仅在同步内等待”规则的原因。


link posted by @Willie 中的一段总结的很好:

You need an absolute guarantee that the waiter and the notifier agree about the state of the predicate. The waiter checks the state of the predicate at some point slightly BEFORE it goes to sleep, but it depends for correctness on the predicate being true WHEN it goes to sleep. There's a period of vulnerability between those two events, which can break the program.

上例buffer.isEmpty()中需要生产者和消费者达成一致的谓词。并且通过确保在 synchronized block 中执行等待和通知来解决协议(protocol)。


本文已在此处改写为文章:Java: Why wait must be called in a synchronized block

关于java - 为什么必须 wait() 始终处于同步块(synchronized block)中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2779484/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com