java - 'fair' 和 'unfair' 锁的内部存储差异

标签 java locking reentrantlock

具有类 Reentrant(true) 锁的 Lock 接口(interface)的工作方式是它使用 阻塞队列 存储想要获取 的线程锁 .以这种方式“先来,先出去”的线程 - FIFO。一切都清楚。
但是“不公平的锁”去哪里了,或者 ReentrantLock(false)。他们的内部实现是什么?操作系统如何决定现在选择哪个线程?最重要的是现在这些线程也存储在队列中还是在哪里? (他们一定在某个地方)

最佳答案

类(class) ReentrantLock 不使用 BlockingQueue .它使用 AbstractQueuedSynchronizer 的非公共(public)子类在幕后。
AbstractQueuedSynchronizer 正如其文档所述,该类维护“先进先出 (FIFO) 等待队列”。这种数据结构对于公平锁和不公平锁是一样的。不公平并不意味着锁会改变排队等待线程的顺序,因为这样做没有任何优势。
关键区别在于不公平锁允许 lock尝试在锁刚刚释放时立即成功,即使还有其他线程等待锁的时间更长。在那种情况下,队列甚至不涉及超车线程。这比将当前线程添加到队列中并将其置于等待状态同时从队列中移除最长等待线程并将其状态更改为“可运行”更有效。
当锁不可用时,一个线程尝试获取它,线程将被添加到队列中,此时,公平锁和不公平锁没有区别(除了其他线程可能在没有排队)。由于没有为不公平锁指定顺序,它可以在幕后使用 LIFO 数据结构,但对于两者只有一个实现代码显然更简单。
对于 synchronized ,另一方面,不支持公平获取,有一些 JVM 实现使用 LIFO 结构。这可能会从一个版本更改为另一个版本(或者甚至相同,作为某些 JVM 选项或环境方面的副作用)。
在这方面另一个有趣的点是 parameterless tryLock() ReentrantLock即使锁处于公平模式,实现也是不公平的。这表明不公平不是这里等待队列的属性,而是对到达的线程进行新的锁定尝试的处理。

Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock. This "barging" behavior can be useful in certain circumstances, even though it breaks fairness.

关于java - 'fair' 和 'unfair' 锁的内部存储差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63431161/

相关文章:

java - 如何正确转义 JSP 标签中的三重嵌套引号

java - 匹配规则集与 Java 中的输入数据集

c# - .NET 字典 : Potential concurrency problems?

Java - ReentrantLock,锁无法解锁

java - 与嵌套锁同步

java - com.lowagie.text.Document.add(Element e) 的 NullPointerException

java - 匹配函数在 Java 中不起作用

php - php中的文件锁定

MySQL MyISAM - 不加锁进行插入

java - ReentrantLock.tryLock(long timeout, TimeUnit unit) 无法获取锁时不超时