class Single { private Single() { System.out.println("ok"); } private static Single instance = new Single(); public static Single getInstance() { return instance; } }
public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { synchronized(LazySingleton.class) { if (instance == null) { instance = new LazySingleton(); } } } return instance; } }
可是因为Java编译器容许处理器乱序执行(指令重排序),上述二、3点的顺序是没法保证的。(意思是可能instance != null时有可能还未真正初始化构造器)。
解决方法是经过将instance定义为volatile的。(volatile有两个语义:1. 保证变量的可见性;2. 禁止对该变量的指令重排序)java
class Single { private Single() {} private static class InstanceHolder { private static final Single instance = new Single(); } public static Single getInstance() { return InstanceHolder.instance(); } }
synchronized
block or method exit) of a monitor happens-before every subsequent lock (synchronized
block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor. (线程安全性主要依赖这条规则)volatile
field happens-before every subsequent read of that same field. Writes and reads of volatile
fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.start
on a thread happens-before any action in the started thread.join
on that thread.public class LazySingleton { private int someField; private static LazySingleton instance; private LazySingleton() { this.someField = new Random().nextInt(200)+1; // (1) } public static LazySingleton getInstance() { if (instance == null) { // (2) synchronized(LazySingleton.class) { // (3) if (instance == null) { // (4) instance = new LazySingleton(); // (5) } } } return instance; // (6) } public int getSomeField() { return this.someField; // (7) } }