首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JAVA中重入锁中公平参数的目的是什么?

JAVA中重入锁中公平参数的目的是什么?
EN

Stack Overflow用户
提问于 2021-12-03 14:54:44
回答 2查看 417关注 0票数 0

我在浏览可重入锁的Java时发现了以下文本:

锁的公平性不能保证线程调度的公平性。因此,使用公平锁的多个线程中的一个可以连续多次获得该锁,而其他活动线程则没有进展,目前也没有保存该锁。

根据我的理解,如果OS调度程序调度相同的线程(之前获取锁),并且再次尝试获取相同的锁,Java将允许它获取并且不服从公平参数值。有人能告诉我公平参数的目的是什么吗?在什么情况下应该使用它。

我只是在想,如果它只是一个优先级值,这可能会影响调度程序,但不能保证线程执行顺序。

EN

回答 2

Stack Overflow用户

发布于 2021-12-03 15:29:50

锁的公平性不能保证线程调度的公平性。因此,使用公平锁的多个线程中的一个可以连续多次获得该锁,而其他活动线程则没有进展,目前也没有保存该锁。

我将“不进展”解释为“由于与所涉锁无关的原因而不进展”。我想他们是想告诉你,“公平”仅仅是指当锁有如此激烈的争议,经常有一个或多个线程等待他们锁定它的时候。

如果线程T释放当前没有其他线程等待的“公平”锁,那么“公平”不会影响下一个线程将得到的锁。这只是线程之间的一场直截了当的竞赛,由操作系统调度程序来调节。

只有当多个线程在等待时,一个公平的锁才会“青睐”等待时间最长的锁。特别是,我希望如果某个线程T释放其他线程正在等待的“公平”锁,然后线程T立即尝试再次锁定它,那么lock()函数将注意到其他等待的线程,并将T发送到队列的后面。

但是,我并不知道它是如何在任何特定的JVM中实现的。

P.S.,IMO,“公平”就像用绷带来止住复合骨折的出血。如果您的程序有一个被激烈争论的锁,以至于“公平”会产生任何不同,那么这就是一个严重的设计缺陷。

同一个Javadoc还说,

与使用默认设置的程序相比,使用许多线程访问的公平锁的程序可能显示较低的总体吞吐量(即速度较慢;通常要慢得多)。

票数 4
EN

Stack Overflow用户

发布于 2021-12-04 01:28:08

ReentrantLock是基于AbstractQueuedSynchronizer实现的,它是一个先进先出(FIFO)的等待队列.

假设三个线程A、B和C依次尝试获取锁,而A获取锁,则B、C将被转换为队列中的AbstractQueuedSynchronizer#Node。这两个线程将被挂起。

当A线程释放锁时,它将唤醒其后续节点(AbstractQueuedSynchronizer#unparkSuccessor),即线程B。线程B将在锁被唤醒后再次尝试获取锁。

假设当B线程被唤醒时,一个D线程突然来尝试获取这个锁。对于一个公平的锁,D线程看到队列中还有其他节点等待获取锁(AbstractQueuedSynchronizer#hasQueuedPredecessors),并将直接挂起。

对于不公平的锁,D线程将立即尝试获取此锁,这意味着它可以尝试“跳转队列”一次。如果这个“队列跳转”成功,那么就可以立即获得锁(这意味着节点B将再次挂起:它在与D线程的竞争中失败,它被切成一行)。如果失败,它将被挂起并作为节点输入队列。

为什么不公平的锁表现更好,什么时候使用公平的锁?

这是来自Java-并发性-实践

在严重争用的情况下,中断锁的性能要比公平锁好得多的原因之一是,在恢复挂起的线程和实际运行线程之间可能会有很大的延迟。假设线程A持有一个锁,而线程B请求该锁。因为锁很忙,所以B被挂起。当A释放锁时,B将被恢复,以便它可以重试。但是,在此期间,如果线程C请求锁,则很有可能C可以获得锁,使用它,甚至在B醒来之前释放它。在这种情况下,每个人都会赢:B不迟于它本来会得到的锁,C得到它的时间要早得多,并且吞吐量得到了提高。 当锁保持时间相对较长或锁请求之间的平均时间相对较长时,公平锁往往工作得最好。在这些情况下,驳船提供吞吐量优势的条件--当锁未被持有,但线程目前正在苏醒以声称它--不太可能保持。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70216266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档