首页 > 解决方案 > Java 监视器的等待集是否优先于条目集?

问题描述

我想问你一个与Java中的多线程有关的问题。

我有一个监视器,多个线程都渴望拥有它。临界区内部this.wait()也是根据某些条件调用的。

AFAIK,监视器有 2 组线程:

notify但是当/notifyAll被调用时它们如何竞争?等待集中的线程在获取监视器方面是否优先于条目集中的线程,或者它们是否移动到条目集中?

我可以确定下notify一个执行的线程将是等待集中的一个吗?

标签: javamultithreadingconcurrencymutexbarrier

解决方案


不,调度程序负责下一个获得锁的线程。可能是等待集中的一个收到通知。它可能是一个刚刚到达并且尚未进入等待集的线程。假设刚刚得到通知的线程接下来会得到监视器是不安全的。

标准建议是在循环中调用 wait 来检查正在等待的条件:

synchronized (lock) {
    while (!condition) {
        lock.wait();
    }
    ...

这样,当一个线程退出等待时,它会与任何尚未等待的线程进行相同的检查,以了解是否继续进行。

如果您需要公平,您希望等待时间最长的线程接下来获取锁,那么您可以尝试 java.util.concurrent.locks 中的显式锁之一,例如ReentrantLock,但请阅读细则:

此类的构造函数接受一个可选的公平参数。当设置为 true 时,在争用情况下,锁有利于授予对等待时间最长的线程的访问权限。否则,此锁不保证任何特定的访问顺序。使用由许多线程访问的公平锁的程序可能会显示出比使用默认设置的程序更低的整体吞吐量(即,更慢;通常要慢得多),但在获取锁和保证不会出现饥饿的情况下具有较小的时间差异。但是请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程之一可能会连续多次获得它,而其他活动线程没有进展并且当前没有持有锁。另请注意,不定时的 tryLock 方法不遵守公平设置。


推荐阅读