- 先写一个简单的懒汉式:
- public class Singleton
- {
- private static Singleton instance = null;
- private Singleton() {}
- public static synchronized Singleton getInstance()
- {
- if(instance == null)
- {
- instance = new Singleton();
- }
- return instance;
- }
- }
- 显然在多线程下肯定是不安全的,故加上synchronized,这样做封锁的是整个对象,性能会降低,
- 因为每次调用getInstance()时都要对对象上锁,事实上只要在第一次调用时会创建对象,以后就不用创建了。
- 改进如下:
- public class Singleton
- {
- private static Singleton instance = null;
- private Singleton() {}
- public static Singleton getInstance()
- {
- if(instance == null)
- {
- synchronized(this)
- {
- if(instance == null)
- {
- instance = new Singleton();
- }
- }
- }
- return instance;
- }
- }
- 似乎解决了之前的问题,性能得到提升,但是还是有问题,原因在于在JAVA指令中创建对象和赋值是分开操作的,
- 也就是instance = new Singleton();语句是分开操作执行的,但是JVM并不保证这两个操作的顺序是先后执行的,
- 它可能为新的Singleton实例分配空间,然后直接复制给instance成员
- 然后再去初始化Singleton实例,假设有线程A和B
- 1,A,B同时进入第一个if判断
- 2,A首先进入synchronized模块,发现instance为null,开始执行instance = new Singleton();
- 3,由于JVM的一些优化操作,JVM先划出了一些空白内存给Singleton的实例instance,但并未初始化instance,A便离开了synchronized模块
- 4,B发现instance不为null便直接离开了
- 5,B打算使用instance实例发现它没有初始化,编译器出错!!!
- 因此最好使用饿汉式!!
复制代码 |