您可以想象对象的创建具有许多非原子功能。首先,您要初始化和发布Holder。但是,您还需要初始化所有私有成员字段并发布它们。
那么,JMM没有规则来进行写入和发布
holder成员字段-
在发生字段写入之前
holder发生
initialie()。这意味着即使
holder不为null,成员字段对其他线程仍不可见是合法的。
您可能最终会看到类似
public class Holder{ String someString = "foo"; int someInt = 10;}holder可能不为null,但
someString可以为null,
someInt可以为0。
据我所知,在x86架构下这是不可能发生的,但在其他情况下可能并非如此。
因此,下一个问题可能是
Why does volatile fix this?
JMM说的是,在volatile存储之前发生的所有写操作对于volatile字段的所有后续线程都是可见的。
因此,如果
holdervolatile是可变的,并且您看到
holder不为null,则基于volatile规则,将初始化所有字段。
为了安全地发布此对象,我们是否必须将持有人初始化设为静态并将其声明为volatile
是的,因为正如我提到的,如果
holder变量不为null,那么所有写操作都是可见的。
如何抛出assertionError?
如果一个线程注意到
holder不为空,并且
assertionError在进入该方法并
n在第一次读取时调用
0(默认值),则第二次读取
n现在可以看到第一个线程的写入。



