我对ReentrantLock
的Condition
有一个困惑。
根据最新的子弹,公平带来了一个明确的顺序锁定要求信号。
但是,以FIFO顺序表示的第一个等待子弹线程的含义是什么?在这种情况下,我推测信令的意思只是“发送信号”,意思是“解除”FIFO顺序中的线程,但是唤醒时的实际查询顺序是由公平性决定的。
有相当多的工作人员与HotSpot内部的cxq和等待队列绑定在一起,这一点我不太理解(不幸的是)。
问题
等待线程是否以FIFO顺序发出信号,意味着等待线程按照它们所停放的顺序(即使锁本身是不公平的)被卸载?
公平是否提供了法庭命令的保证,这是必要的,因为在一般情况下存在无公园的竞争?
发布于 2021-01-14 16:01:29
正如“公平”和“不公平”锁内部存储的差异中所解释的,“公平”和“不公平”之间的实际区别不是队列的组织,而是在不公平模式下,即使队列中已经有等待线程,试图获取锁的线程也可能成功。这样的超车线程根本不会与队列交互。
调用Condition
上的一个Condition
方法的线程必须已经拥有关联的锁并将其释放,以便另一个线程能够获取它、满足条件并调用signal
或signalAll
。因此,线程必须自己排队,以便其他线程知道要向哪个线程发送信号。当调用signal
时,等待条件时间最长的线程将从FIFO中获取。
信号线可能会被取消,但也有可能它还没有停放。在任何一种情况下,它必须重新获得锁,而这一重新获取是受锁的公平保证。当线程调用signal
时,它必须拥有锁。因此,发出信号的线程不能立即成功。当锁被释放时,可能会有多个线程之间的竞争。
但是,对于一个条件采用FIFO顺序的信令意味着,当两个或多个线程在相同的条件下等待,其中一个被发出信号时,它将是等待时间最长的线程,其他线程都无法超车,甚至对于不公平的锁也是如此。只有当多个线程发出信号或其他线程不等待条件时,尝试获取锁时,不公平锁的获取顺序才是任意的。此外,正如链接的答案所提到的,tryLock()
甚至可能在一个公平的锁上超过。
发布于 2021-01-13 13:56:22
阅读ReentrantLock (Java12)的源代码,我们可以看到,与公平和不公平的ReentrantLock只有很小的区别。区别在于扩展java.util.concurrent.locks.AbstractQueuedSynchronizer.的类。在一种情况下,它是FairSync,而另一种情况是NonfairSync。这两种方法都是在ReentrantLock中定义的,唯一的区别是FairSync在方法tryAcquire中实现了另一个检查。阅读代码似乎是在最优的条件下,也是在不公平的ReentrantLock先进先出是受尊重的,但这并不保证由于取消,超时或类似的。在公平的ReentrantLock中,在获取锁之前的任何线程(如果从队列中取消),请重新检查是否存在旧线程。我不确定是否理解第二个问题,但请注意,释放锁的线程将线程从队列中卸载。另外,如果释放锁的线程卸载队列中的旧线程,这不足以避免饥饿,因为第三个线程可以在退出线程卸载等待线程之前同时获取锁。在公平模式下,每当一个新线程试图获得锁和这个被授予者FIFO并避免饥饿时,都会对所有线程进行检查。
等待线程的外部中断不会更改队列顺序。
https://stackoverflow.com/questions/65699934
复制相似问题