Java LockSupport 内存一致性

8

Java 6 API的问题。调用LockSupport.unpark(thread)是否与刚解锁的线程中LockSupport.park的返回具有 happens-before 关系?我强烈怀疑答案是肯定的,但Javadoc似乎没有明确提到。

3个回答

7
我刚发现了这个问题,因为我自己也在问同样的事情。根据甲骨文研究员David Dice的this article,答案似乎是。以下是文章中相关的部分:

如果一个线程在park()中被阻塞,我们保证后续的unpark()会使其准备就绪。一种完全合法但低质量的park()unpark()实现是空方法,在这种方法中程序退化为简单的自旋。事实上,这是正确使用park()-unpark()的试金石。

空的park()unpark()方法不会给你任何关系的保证,因此为了使您的程序100%可移植,您不应该依赖它们。
再次提醒,LockSupport的Javadoc 中写道:
这些方法被设计成用作创建更高级别同步工具的工具,并不适用于大多数并发控制应用程序。 park 方法仅用于以下形式的构造中:
while (!canProceed()) { ... LockSupport.park(this); }
由于您必须显式检查某些条件,该条件将涉及 volatile 或正确同步的变量,因此 park() 的弱保证实际上不应该是问题,对吗?

2
谢谢您的回答。我现在记不起来为什么想知道这个了。我猜想当运行线程更新条件并调用unpark时,是否可以保证被唤醒的线程会以一致的状态看到更新后的条件。似乎没有保证,因此唯一安全的选择是为条件更新显式地安排内存屏障。 - Lachlan
我明白了。如果park()unpark()之间存在先行发生的关系,那么条件就不需要涉及内存屏障。所以这个问题仍然是有效的。 - rolve

5

如果没有明确记录,那么您不能依赖它来创建先后发生(happens before)关系。

具体来说,在Hotspot代码中,LockSupport.java只是简单地调用Unsafe.park和.unpark!

先后发生关系通常来自于易失性状态标志的写-读对,或类似的东西。

请记住,如果没有记录为创建先后发生关系,则必须将其视为不会创建,即使您可以证明在特定系统上可以创建。未来的系统和实现可能不会。他们之所以保留这种自由是有充分的理由的。


0

我已经查看了JDK代码,看起来LockSupport方法通常在同步块之外调用。因此,你的假设似乎是正确的。


1
很抱歉评论这样一个老旧的答案,但由于问题涉及Java API而不是Sun/Oracle提供的实现,因此查看JDK如何使用LockSupport并不完全正确。 JDK开发人员可能会对自己的实现做出假设,而可移植应用程序则不应该。此外,有一些方法可以实现happens-before关系,而不涉及任何synchronized块。 - rolve
“...查看了JDK代码”:您能否请提供OpenJDK的hg URL? - kevinarpe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接