根据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。安全发布惯用语,另一种情况 - “从静态初始化程序初始化对象引用”。现在看来这些都是选择。
答案 0 :(得分:2)
除final
之外,我不知道任何事情,只需看一眼http://java.sun.com/docs/books/jls/third_edition/html/memory.html就可以证实这一点。第17.4章处理除final
之外的所有内容,这在17.5中单独解释。
但应该注意的是,JVM内部的任何内容必须始终可见,然后才能在Java代码中引发数据竞争。这主要影响数组长度,虚拟表指针和字符串内容。这些永远不会被视为未初始化或不一致。
答案 1 :(得分:2)
您可以在Java In Concurrency中找到的所有案例列表:
安全地发布对象,两者都是 引用对象和 必须使对象的状态可见 其他线程同时。一个 正确构造的对象可以 安全发布者:
初始化对象引用 静态初始化器;
将对它的引用存储到 volatile字段或AtomicReference;
将参考文献存入决赛 正确建造的领域 宾语;或
将对它的引用存储到字段中 这是由一把锁妥善保护的。
答案 2 :(得分:1)
静态初始化在synchronized(class)
内完成,所以非常强大。
虽然final
语义较弱,但我怀疑实现是否真的那么弱。
Doug Lea提出了更原始的围栏,http://cs.oswego.edu/pipermail/concurrency-interest/2009-January/005743.html