AbstractQueuedSynchronizer 的 JavaDoc 不清楚

问题描述 投票:0回答:1

我认为 JavaDoc 中关于 AbstractQueuedSynchronizer 的两句话不清楚/具有误导性,因此我想澄清这些问题。

第一句话说:

尽管此类基于内部 FIFO 队列,但它不会自动强制执行 FIFO 获取策略。

上面这句话到底是什么意思?查找类本身的源代码(其中有几个标记为

final
的方法),我目前只看到一种无法强制执行 FIFO 的情况,即当
tryAcquire
返回
true
时。当
tryAcquire
返回
false
并且调用者线程必须暂停时,我找不到任何绕过 FIFO 的方法。如果我的假设是正确的,文档不应该更清楚吗?

第二句说:

因为获取中的检查是在排队之前调用的,所以新获取的线程可能会抢在其他被阻塞和排队的线程之前。但是,如果需要,您可以定义 tryAcquire 和/或 tryAcquireShared 以通过内部调用一个或多个检查方法来禁用插入,从而提供公平的 FIFO 获取顺序。

这里的barging到底是什么意思?文档是不是又在讲获取线程没有停放的情况了?

我目前的理解是这样的:只要获取线程没有parked,除了FIFO以外的策略都是可以的。如果获取线程必须停放,则将使用 FIFO。

您同意我的说法还是我理解错了?开个BUG让Oracle来修复有意义吗?

java multithreading synchronization locking javadoc
1个回答
0
投票

查看

ReentrantLock
的源代码,看看它在实践中是如何实现的。
NonfairSync

        protected final boolean tryAcquire(int acquires) {
            if (getState() == 0 && compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

FairSync

        protected final boolean tryAcquire(int acquires) {
            if (getState() == 0 && !hasQueuedPredecessors() &&
                compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

如您所见,

FairSync.tryAcquire()
还会检查
!hasQueuedPredecessors()
,正如
AbstractQueuedSynchronizer
的 javadoc 建议的那样:

因为获取中的检查是在排队之前调用的,所以新获取的线程可能会在其他被阻塞和排队的线程之前“插入”。但是,如果需要,您可以定义 tryAcquire 和/或

tryAcquireShared
以通过内部调用一个或多个检查方法来禁用插入,从而提供
fair
FIFO 采集顺序。特别是,如果 tryAcquire(专门设计用于公平同步器使用的方法)返回
false
,则大多数公平同步器可以定义
hasQueuedPredecessors()
来返回
true
。其他变化也是可能的。

简单来说,以下案例说明了其中的差异:

当前锁所有者释放锁,并且在释放期间,从 FIFO 队列中等待时间最长的线程被释放。
  1. 在未停放的线程恢复执行并获取锁之前,另一个线程也尝试获取该锁。
    • FairSync
    • 停放新线程并将其放在 FIFO 队列的末尾:这里所有线程都按 FIFO 顺序获取锁
    • NonfairSync
    • 允许新线程获取锁:这里我们失去了公平性,但获得了更高的性能
      
      
© www.soinside.com 2019 - 2024. All rights reserved.