单例模式-DoubleCheck

1.单例模式理解:是为了满足一些场景,一个对象只能创建一个实例对象的场景。
流程:
1.构造方法私有化,
2.声明对象 位静态
3.类方法返回实例化后的对象。

2.将单例模式分为两类 懒汉式和饿汉式:

懒汉式:特点在定义Singleton是就new

public class Singleton{
		private static Singleton singleton=new Singleton();
		private Singleton(){}
		public static Singleton newInstance(){
			 return singleton;
		}
}

优点:简单,而且保证了线程安全,不管有多少个线程访问都只返回一个Singleton实例化对象

饿汉式单例模式:
1.普通

public class Singleton{
		private static Singleton singleton;
		private Singleton(){}
		public static Singleton newInstance(){
				if(singleton==null){		
					 singleton=new Singleton();
				}		
				return singleton; 
		}
}

线程不安全:if判断确实可以保证只创建一个Singleton的实例对象。
但是在多线程并发场景下,由于没有加锁,多个线程可能都会进入到if中,那么这些线程就可以进行对象实例化操作产生多个对象。

	if(singleton==null){		
  		  //多个线程进入id判断里面,
		  singleton=new Singleton();
	}	

双层检验锁单例模式:

public class Singleton{
		private static volatile Singleton singleton;
		private Singleton(){}
		public static Singleton newInstance(){
			   if(singleton==null){
			   			//1
			 		synchronized(Singleton.class){
			 			  		//2
			 			  		if(singleton==null){
			 						
			 							singleton=new Singleton();
			 				   		}
			 			}
			     }
			     return singleton;//3
		}
}

按照上面的注释:来分析上面的代码:

1.在调用类方法newInstance的时候所有线程都可以进入//1中
2.多个线程中只有一个线程会拿到锁 进入同步代码块
3.拿到锁后要再次判断当前对象引用是否指向实例,因为在这个线程之前还会有别的线程拿到锁执行同步代码块。

到此流程基本结束:还有几个问题:

1.singleton为什么要用volatile修饰?
首先,synchronized 保证了只有一个线程对singleton进行实例操作,但是操作的对象是引用数据类型,换句话说该操作不是原子的。那么久可能发生指令重排。

正常情况:实例化对象的流程:
	1.在堆上开辟空间
	2.属性初始化
	3.将栈上空间指向堆。
	正常是1——>2——>3
	
	但是如果没有volatile关键字就可能发生指令重排:
	假设 1——>3——>2
	如果没有属性的话没有问题,
	
	一旦有了属性,假设现在有两个属性:
	name=“hahaha”,
	age=12;
	由于3步骤先执行,singleton已经不为空了,
	当有新的线程尝试获取Singleton实例,到了外层判断,直接返回。
	导致的结果就是,有能属性还没有来的及初始化就直接返回了,或者初始化了name..

2.为什么要有双重if判断:

内部的if是保证只有一个Singleton实例化对象被创建。
外层的if实际上是为了保证性能:
当Singleton已经被创建了,不进入内部,直接返回。

可以把这种机制:当做一个限量发售的鞋,
把多线程当做在排队等待鞋的人。
当一个人进入后买了这双鞋		实际上已经没有这双鞋了
通常做法是在门口立一个牌子,鞋已经售空 人看到这个牌子就可以直接走了
 相当于外部的i	f)。
 如果没有这个牌子,外面的人就不知道鞋已经卖完,还在不断排队进入鞋店,浪费资源
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值