Java中的条件如何知道触发哪个线程?

问题描述 投票:2回答:3

我正在阅读Java中的Condition Documentation,我有一个误解。阅读他们的puttake的例子,如你所见,他们在函数put中有代码行:notEmpty.signal()其中notEmpty是来自lock的条件。

我想知道如果有多个线程正在等待notEmpty的信号怎么办。在这种情况下会发生什么以及触发哪个线程?

java multithreading concurrency operating-system
3个回答
1
投票

它会对处理它的操作系统进行系统调用。 JVM不知道哪个线程会被唤醒。

线程由操作系统而不是JVM管理,因此它能做的最好的事情就是进行正确的系统调用,然后让操作系统完成剩下的工作。


1
投票

我认为线程调用await()首先会被触发,而结论来自source code

await()做了什么?

  1. 创建一个等待节点并将该节点添加到由Condition维护的fifo队列
  2. 释放锁,你在调用await()之前看到,你需要调用lock.lock()
  3. 测试是否在步骤2中由其他线程调用signal()。如果没有则停放当前线程。

signal()做了什么?

  • 获取由Condition维护的队列中的节点并将其放入由Lock维护的队列中,因此如果一个线程首先调用await(),它将首先进入Lock的队列

什么时候停放的线程会被唤醒?

显然,在Condition.signal()之后会调用Lock.unlock(),Lock.unlock()将从头到尾从Lock的等待队列中获取一个节点,参见AbstractQueuedSynchronizer#unparkSuccessor,所以如果你先输入Lock的队列,你会先被触发。


1
投票

我想知道的是,如果有多个线程正在等待notEmpty的信号怎么办?在这种情况下会发生什么以及触发哪个线程?

正如其他人已经回答的那样,您无法知道将触发哪个线程。

所以我猜这种方法只适用于两个线程?

取决于“这种方法”的含义。有几个线程等待相同的条件通常是有意义的。诀窍在于,既然你不知道哪个线程会被唤醒,你应该以这样一种方式编写代码,使得哪个线程被唤醒无关紧要。

这是一个在编写多线程代码时应该尝试遵循的良好实践示例,即:当需要完成工作时,哪个线程可以正常工作并不重要。

© www.soinside.com 2019 - 2024. All rights reserved.