Java并发实践书里已经给出了不安全发布的例子
public class Holder
{
private int n;
public Holder(int n)
{
this.n = n;
}
public void assertSanity()
{
if (n != n)
throw new AssertionError("This statement is false.");
}
}
上面的代码看起来是线程安全的。如果 n 是公共变量,则不是线程安全的。书上的例子有错吗?
安全出版是关于内存可见性。内存可见性的概念比其他线程安全问题(例如竞争条件)要复杂一些。
当一个线程按某种顺序执行的操作似乎对另一个线程按不同的顺序执行时,就会出现内存可见性问题(这可能是由编译器或 CPU 进行的优化引起的)。
在你的情况下:
// Thread A
h = new Holder(42);
// Thread B
h.assertSanity();
对于线程 A,n
肯定是之前初始化过的h
.
但在没有安全发布的情况下,不能保证线程 B 是相同的。线程 B 可能会看到h
处于初始化状态,但是n
还不会被初始化。此外,国家n
正如线程 B 所观察到的,在评估期间可能会发生变化n != n
,导致assertSanity()
抛出异常。
请注意,此问题并非在所有情况下都一定会发生。您可能永远不会看到这种情况发生,但 Java 内存模型仍然不能保证这种情况下的正确性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)