java - Java 监视器的等待集是否优先于条目集?
问题描述
我想问你一个与Java中的多线程有关的问题。
我有一个监视器,多个线程都渴望拥有它。临界区内部this.wait()
也是根据某些条件调用的。
AFAIK,监视器有 2 组线程:
- 入口集 - 刚到达的线程聚集并等待轮到他们拥有监视器
- 等待集 -
this.wait()
等待被唤醒的线程
notify
但是当/notifyAll
被调用时它们如何竞争?等待集中的线程在获取监视器方面是否优先于条目集中的线程,或者它们是否移动到条目集中?
我可以确定下notify
一个执行的线程将是等待集中的一个吗?
解决方案
不,调度程序负责下一个获得锁的线程。可能是等待集中的一个收到通知。它可能是一个刚刚到达并且尚未进入等待集的线程。假设刚刚得到通知的线程接下来会得到监视器是不安全的。
标准建议是在循环中调用 wait 来检查正在等待的条件:
synchronized (lock) {
while (!condition) {
lock.wait();
}
...
这样,当一个线程退出等待时,它会与任何尚未等待的线程进行相同的检查,以了解是否继续进行。
如果您需要公平,您希望等待时间最长的线程接下来获取锁,那么您可以尝试 java.util.concurrent.locks 中的显式锁之一,例如ReentrantLock,但请阅读细则:
此类的构造函数接受一个可选的公平参数。当设置为 true 时,在争用情况下,锁有利于授予对等待时间最长的线程的访问权限。否则,此锁不保证任何特定的访问顺序。使用由许多线程访问的公平锁的程序可能会显示出比使用默认设置的程序更低的整体吞吐量(即,更慢;通常要慢得多),但在获取锁和保证不会出现饥饿的情况下具有较小的时间差异。但是请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程之一可能会连续多次获得它,而其他活动线程没有进展并且当前没有持有锁。另请注意,不定时的 tryLock 方法不遵守公平设置。
推荐阅读
- hyperledger-fabric - 带有 configtxlator Hyperledger Fabric 1.4.6 的错误解析器块
- php - 我可以设置 web.config 文件的基本 URL 吗?
- python - 使用 for 循环有没有办法控制哪个 # 循环将值附加到列表中?
- java - 我正在尝试打印我创建的对象 person p1 的地址 a1。Person 构造函数也接受 Address 对象
- python - 如何将输出变成列表
- regex - ${something} 之间的任何内容的正则表达式
- openshift - Openshift 设置环境或修补环境
- javascript - 映射到 lambda 函数 JavaScript 中的对象 - 为什么没有括号它不能工作?
- laravel - 我应该复制控制器,还是使用 artisan:make 控制器?
- python - ns3,Python3 没有名为“ns”的模块