java - 如果我们在 Java 中的当前线程多次调用 condition.await() 会发生什么
问题描述
我想了解当我们执行以下代码片段时真正发生了什么。
当一个线程执行 someMethod() 并命中 while 循环时,如果它一次又一次地调用 await 方法会发生什么?Condition/ReentrantLock 如何存储/维护线程上下文?
另外,一旦一个线程调用了await(),就意味着它释放了当前的锁,进入了等待状态。这是否意味着另一个线程可以获得锁?如果是这样,围绕 await() 方法编写一个 while 循环有什么用?
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
...
...
public void someMethod() {
lock.lock();
try {
for (int i = 2; i < n; i = i + 2) {
while (state != 2) {
condition.await();
}
printNumber.accept(i);
r.run();
state = 0;
condition.signalAll();
}
} finally {
lock.unlock();
}
}
如果我的理解有误,请纠正我。提前致谢。
解决方案
该等待循环的要点显然是等到状态为 2。从等待调用中醒来仅意味着您已经醒来。这并不意味着状态为 2。
逻辑和我半夜起床,看看表,然后决定回去睡觉的时候是一样的。:-)
请注意Condition 的文档明确指出可能会发生虚假唤醒。这意味着任何不检查实际所需状态的 Condition.await 使用几乎肯定存在错误。
同时,这段代码似乎有缺陷。你知道你不会signalAll
在线程等待时执行调用await
,对吧?因为线程正在等待await
。需要有一些其他线程,执行不同的代码,可以发出条件信号,以便让该线程摆脱等待。
你的问题:
我想了解当我们执行以下代码片段时真正发生了什么。
使用显示的代码,线程将永远处于await
调用中,因为没有显示可以唤醒它的代码。
(根据文档,存在虚假唤醒的可能性,如果发生这种情况,while 循环会将线程重新置于等待状态,因为等待的内容不会改变。)
关于“一次又一次地调用 await”——好吧,你不能在等待的时候调用 await——因为当你不跑步时,你无处可调用任何东西。因此,第一次和后续调用之间没有区别。在每种情况下,调用线程都会进入睡眠状态,直到随后发出条件信号。
至于锁定 - 在等待时释放锁,并在唤醒时重新获取。这是实际需要;大概在您的示例中,锁正在保护对“状态”的访问,并且任何想要修改状态并唤醒服务员的代码最好在锁的保护下进行。
推荐阅读
- google-sheets - 强制复制受保护的谷歌表格
- python - 如何根据 Python 中的最小值、最大值和可能值生成阶梯分布值?
- azure - 如何在 Azure DevOps Board 中设置 WIP 限制 - Sprint 视图
- sql - SQL:如果两个条件都满足而不是在多个where中单独排除,如何仅排除条件?
- php - yii2中camelcase字段模型的问题
- typescript - 为 Azure Functions 编写可测试的入口点
- flutter - 在颤动中更改文本字段的突出显示颜色
- java - Android Studio - 在另一个 aar 模块中隐藏 aar 模块依赖项
- python - 从字节创建固定大小元组的numpy数组的有效方法
- java - 为 HttpClientErrorException 设置 Httpstatus 499