单例模式的演化

在工作或者各种面试中,面试官都很爱问单例模式的懒汉模式之类的问题,在工作中,各种初始化(ActiveMQ等)都有可能用到,所有下面就具体讲一下单例模式的演化过程:

1. 一个最简单的单例模式:

class Singleton1{
	
	private static Singleton1 singleton1 = null;
	
	public static Singleton1 newInstanceSimple(){
		
		if(singleton1 == null){
			singleton1 = new Singleton1();
		}
		
		return singleton1;
	}
}


 但是这个代码不是线程安全的,如果两个线程(A,B)同时访问单例模式中的方法,如果线程A运行到第8行之后被线程调度器调度不再执行,这是线程调度器调度B运行这个方法,会创建一个单例对象,而线程调度器又调度A线程,A线程又创建一个单例对象,那么,内存中就有两个Singletion对象。

2.改进一下

class Singleton2{
	
	private static Singleton2 singleton2 = null;
	
	public static synchronized Singleton2 newInstanceSimple(){
		
		if(singleton2 == null){
			singleton2 = new Singleton2();
		}
		
		return singleton2;
	}
}

 这样虽然保证了线程安全,但是又会产生性能的问题,例如多个线程访问这个方法,返回singleton2对象的操作是很快的(就一条指令),但是synchronized关键字是很花性能的。

3.路漫漫,继续改进

 

class Singleton3 {

	private static Singleton3 singleton3 = null;

	public static Singleton3 newInstanceSimple() {

		synchronized (Singleton3.class) {
			if (singleton3 == null) {
				singleton3 = new Singleton3();
			}
		}
		return singleton3;
	}
}

 虽然把synchronize关键字放在了函数内部,但是效率还是不怎么高,继续改

4. 下面这一招叫做双重锁定检查(DCL)

  

class Singleton4 {

	private static Singleton4 singleton4 = null;

	public static Singleton4 newInstanceSimple() {

		if (singleton4 == null) {
			synchronized (Singleton4.class) {
				if (singleton4 == null) {
					singleton4 = new Singleton4();
				}
			}
		}
		return singleton4;
	}

 除了第一次创建访问同步块,其他访问都都不需要访问同步块,达到要求了吗?

 如下场景:

 singleton4 = new Singleton4();并非原子操作()(原子操作的意思就是这条语句要么就被执行完,要么就没有被执行过,不能出现执行了一半这种情形)。事实上高级语言里面非原子操作有很多,我们只要看看这句话被编译后在JVM执行的对应汇编代码就发现,这句话被编译成8条汇编指令,大致做了3件事情:

  1)创建内存给Singleton4

 2)调用Singletion4的init()方法进行初始化

 3)singleton4指向Singletion4内存

java编译的时候(早起编译还是晚期编译?)时候会进行指令重排序,很有可能顺序不是 1-2-3,如果是1-3-2,那么一个线程访问到第三步的时候,还没执行第二步,被线程调度器调度不再执行,然后另外一个线程执行,实例没有进行初始化,如果访问这个对象的一些方法,就会报错,那么怎么防止这种指令重排序呢,就用volatile关键字,但是最好保证在jdk1.5之后,代码如下:

	class Singleton5 {

		private static volatile Singleton5 singleton5 = null;

		public static Singleton5 newInstanceSimple() {

			if (singleton5 == null) {
				synchronized (Singleton5.class) {
					if (singleton5 == null) {
						singleton5 = new Singleton5();
					}
				}
			}
			return singleton5;
		}

 

 

猜你喜欢

转载自chenghao666.iteye.com/blog/2289509