安全出版没有发生 – 之前? 无论如何除了最后?
根据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