singlon = new SingleInstance() 这个动作不是原子的,正常来说按顺序可以分为三步:1.申请一段内存空间来保存新对象;2.调用构造方法初始化这个新对象;3.将singlon变量引用指向这段将内存地址。
使用volatile的原因是禁止指令重排。如果不用volatile,可能执行顺序是1-->3-->2。当前一个线程执行完3之后,singlon变量的指向已经不为null(但其内存空间还没经过2的初始化,该对象还是个半成品不应该被使用),可能被后来的线程在最外层的if判断中判断成立并被返回使用。其他线程一旦使用了这个半成品对象的内部字段,就会出现空指针。
由Synchronized的内存可见性说起在Java中,我们都知道关键字synchronized可以用于实现线程间的互斥,但我们却常常忘记了它还有另外一个作用,那就是确保变量在内存的可见性 - 即当读写两个线程同时访...