其他分享
首页 > 其他分享> > 手写双重校验锁实现对象单例并附详细解释说明

手写双重校验锁实现对象单例并附详细解释说明

作者:互联网

public class Singleton{

	private volatile static Singleton uniqueInstance;
	
	private Singleton(){
	}
	
	public static Singleton getUniqueInstance(){
	
		if(uniqueInstance==null){
		
			synchronized(Singleton.class){
			
				if(uniqueInstance==null){
				
					uniqueInstance=new Singleton();
					
					}
				}
			}
		return uniqueInstance;
	}
}

说明:

  1. 由于构造函数私有,我们获取Singleton类的实例化对象只能通过Singleton.getUniqueInstance()的方式,而无法在外界通过new或者其他方法创建此类的实例,并且由于此成员变量被static修饰,使得实例对象属于类本身且只有唯一一个。
  2. volatile关键字可以防止jvm指令重排

因为 uniqueInstance = new Singleton() 这句话可以分为三步:
1. 为 singleton 分配内存空间;
2. 初始化 singleton;
3. 将 singleton 指向分配的内存空间。
但是由于JVM具有指令重排的特性,执行顺序有可能变成 1-3-2。 指令重排在单线程下不会出现问题,但是在多线程下会导致一个线程获得一个未初始化的实例。例如:线程T1执行了1和3,此时T2调用 getInstance() 后发现 singleton 不为空,因此返回 singleton, 但是此时的 singleton 还没有被初始化。
使用 volatile 会禁止JVM指令重排,从而保证在多线程下也能正常执行。

  1. synchronized加在getUniqueInstance方法上这样虽然能保证只有一个线程执行getUniqueInstance()方法,但是缺点在于锁的粒度太大了,多个线程同时调用getUniqueInstance()时,其他线程都会被阻塞,毕竟大多数情况下对象已经存在。
  2. 第二次判断是为了防止多个线程同时完成第一次判断为null,A线程获得锁后new一个对象释放锁,此时B线程也获得锁如果没有第二次判断B线程也会new一个对象。

标签:Singleton,校验,singleton,getUniqueInstance,uniqueInstance,线程,单例,new,手写
来源: https://blog.csdn.net/qq_28123419/article/details/114645598