上述的doucleCheck = new DoucleCheck();代码有问题:
其底层会分为三个操作:
1. 分配一块内存。
2. 在内存上初始化成员变量。
3. 把doucleCheck 引用指向内存。
在这三个操作中,操作2和操作3可能重排序,即先把doucleCheck 指向内存,再初始化成员变量,因为 二者并没有先后的依赖关系。此时,另外一个线程可能拿到一个未完全初始化的对象。这时,直接访问 里面的成员变量,就可能出错。这就是典型的“构造方法溢出”问题。
解决办法也很简单,就是为doucleCheck 变量加上volatile修饰。 volatile的三重功效:64位写入的原子性、内存可见性和禁止重排序。