问题 Java:等待同步块,谁先走?


这个问题的灵感来自于 这个问题

如果有多个线程在等待 synchronized 阻止,锁定变得可用,谁先走?它是由线程优先级(然后先来先服务)?

并且适用相同的规则 notify (有多个 wait线程)?


3440
2017-10-15 07:06


起源

如果您正在寻找“公平锁定”,那么请查看java.util.concurrent包。例如,ReEntrantLocks是公平的。公平性来自这样一个事实,即优先级最长的等待线程,类似于进程调度中的“老化”概念。 - questzen


答案:


据这家伙说: http://tutorials.jenkov.com/java-concurrency/starvation-and-fairness.html

Java不对序列发出任何保证。所以我猜它不是基于线程优先级

我将尝试进一步研究Java如何确定谁先行的解释。


8
2017-10-15 07:18



+1有趣。事实证明,并发包中的锁具有可选的公平模式,在这种情况下它们可以工作为fifo。如果不是,那就是任意的。我本以为线程优先级应该在这里发挥作用。 - Thilo
我同意这将是“自然”的选择。 - Mikkel Gadegaard
公平性是有代价的,并且可预测性是以牺牲大吞吐量下降为代价的。此外,公平性要求会阻止VM在实施锁定获取时可能会做的大量优化(例如薄自旋锁等)。 - sjlee
关于这个的一个问题:如果thread1是监视器的持有者而其他线程正在等待,那么thread1是否可以解锁并在“周围”竞争并在任何已经等待的线程之前再次获得锁定? - dmansfield
@dmansfield我不能给出任何确定的答案,但它就像我的代码中发生的那样。如果有人有更正式的答案,我想听听。 - Erhannis


其他人提到了公平锁的可用性。如果您真的关心谁先行,那么您可能会遇到实时问题。在这种情况下,您可以使用RTSJ,其中指定了锁获取的排序和其他语义。具体细节见 RTSJ规格 下 同步。引用理由部分:

Java的同步代码规则   提供互斥的手段   但不要阻止无限制的优先权   反转因而不足   用于实时应用程序。这个   规范加强了   同步代码的语义   强制优先反转控制,   特别是通过装修课程   优先级继承和优先级   天花板仿真。优先   继承得到更广泛的实施   在实时操作系统和   因此是必需的并且是最初的   这个默认机制   规范。


4
2017-10-18 23:12





为你的第二个问题

其中一个被选中被唤醒。选择是任意的,由实施决定。线程通过调用其中一个wait方法等待对象的监视器。

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#notify()


1
2017-10-15 07:16



知道Hotspot如何处理这个问题? - Thilo
如果我将这两个答案与Thread优先级一起使用而不会导致Linux上的OS线程优先级(至少在大多数情况下),那些优先级似乎没有做太多... - Thilo
@Thilo这取决于实施。我不能说这是依赖操作系统的。 - Jigar Joshi
@Thilo,你打算根据行为编写代码吗? - Thorbjørn Ravn Andersen


它取决于线程优先级和线程调度算法,并且同步块上的锁定也不“公平”。这意味着如果有2个等待线程具有相同的优先级,并且第一个线程等待的次数超过第二个线程,这并不一定意味着将首先执行第一个线程。


0
2017-10-15 07:48



你是说先优先考虑更优先吗? - Thilo
对不起,我不是这么说的,我错过了那个案子。我是说,由于公平性,即使优先级较高的线程也可以在优先级较低的线程之后执行。这是因为不公平的锁提供了较弱的活跃度保证,要求所有线程最终获得锁。 - punkers