我有一个 ReentrantLock,一堆操作正在锁定,它是用new ReentrantLock(true)
. 有没有办法让线程“闯入”锁并在释放之后但在任何其他线程之前获取它?
我考虑了 timed 和 untimed 的各种组合tryLock
:
tryLock()
如果它已经解锁并且线程正在等待,它本身将插入锁,但不会等待锁变得可用。- 与超时相同的方法是公平的。
- 将两者结合起来是行不通的,因为如果它在开始时被锁定,基于超时的 tryLock 将退回到公平调度。
还是我错了?
我有一个 ReentrantLock,一堆操作正在锁定,它是用new ReentrantLock(true)
. 有没有办法让线程“闯入”锁并在释放之后但在任何其他线程之前获取它?
我考虑了 timed 和 untimed 的各种组合tryLock
:
tryLock()
如果它已经解锁并且线程正在等待,它本身将插入锁,但不会等待锁变得可用。还是我错了?
正如您在此处看到的,ReentrantLock
用作AbstractQueuedSynchronizer
实际的线程队列实现。看到没有一个方法是可覆盖的,你不能轻易做到这一点,即用优先级队列替换标准线程队列。
但正如它在文档中所说:“这个类为同步提供了一个高效和可扩展的基础,部分是通过将它的使用范围专门用于可以依赖 int 状态、获取和释放参数以及内部 FIFO 等待队列的同步器。当这还不够,您可以使用原子类、您自己的自定义 java.util.Queue 类和 LockSupport 阻塞支持从较低级别构建同步器。”
所以这就是你需要做的:建立你自己的锁。您的主要目标是让该release
方法使用优先级队列来做出决定。如果性能不是问题,您可以只使用标准PriorityQueuesynchronized
,您可以使用ReentrantLock
或任何其他可用的标准锁使其读写线程安全。线程安全的优先级队列很难获得。但是,如果性能很重要,您可能会对 2003 年的这篇论文感兴趣。
但是,由于用户可以在任何给定时间修改线程的优先级,因此在获得下一个人之前,使用基本队列并使用稳定排序(以免弄乱具有相同优先级的线程的顺序)可能是最简单的。当然,如果你想将它用于高争用的关键部分,性能会很差。