安全出版没有发生 – 之前? 无论如何除了最后?

根据JCP(16.2.2。安全出版物):

这种情况发生之前 – 保证实际上是一种比安全出版物更强的可见性和排序承诺 。 当X安全地从A发布到B时,安全发布保证了X的状态的可见性,但不保证A可能触及的其他变量的状态。 但是如果A在队列中放置X,那么在B从该队列中取出X之前,不仅B在A离开它的状态下看到X(假设X后来没有被A或其他任何人修改过),但B看到A在切换之前所做的一切(再次,同样需要注意)

我想知道什么时候安全发布可以没有发生 – 也就是说没有使用volatile / atomics或同步(或通过使用任何内部列出的AQS之类的框架)?

一种情况是不可变对象中的最终字段,您可以将其发布为没有任何其他步骤。

还有其他案件吗?

UPD:重新阅读3.5.3。 安全发布惯用语,另一种情况 – “从静态初始化程序初始化对象引用”。 现在看来这些都是选择。

除了final之外我什么都不知道,只要看一眼http://java.sun.com/docs/books/jls/third_edition/html/memory.html似乎证实了这一点。 第17.4章涉及除final之外的所有内容,在17.5中单独解释。

但应该注意的是,JVM内部的任何内容必须始终可见,然后才能在Java代码中引发数据竞争。 这主要影响数组长度,虚拟表指针和字符串内容。 这些永远不会被视为未初始化或不一致。

您可以在Java In Concurrency中找到的所有案例列表:

要安全地发布对象,必须同时使对象的引用和对象的状态对其他线程可见。 正确构造的对象可以通过以下方式安全发布:

从静态初始化程序初始化对象引用;

将对它的引用存储到volatile字段或AtomicReference中;

将对它的引用存储到正确构造的对象的最终字段中; 要么

将对它的引用存储到由锁正确保护的字段中。

静态初始化在synchronized(class) ,所以它非常强大。

虽然final语义较弱,但我怀疑实现是否真的那么弱。

Doug Lea提出了更原始的围栏建议, http://cs.oswego.edu/pipermail/concurrency-interest/2009-January/005743.html