高并发基础之单例模式(六)

先说下单例模式  在java中的体现

饿汉模式

public class Test1 {

	public static Object object = new Object();
	
	private Test1(){}
	
	public static Object getObject(){
		return object;
	}
}
懒汉模式

public class Test2 {

	private static Object object = null;
	
	private Test2(){}
	
	private static Object getObject(){
		if(object == null){
			object=new Object();
		}
		return object;
	}
}

通常我们接触到的单例模式上的体现也就这两种了 ,那么他们在多线程中会有什么样的体现呢?

第一种饿汉模式在多线程中是线程安全的,但是启动时间会变慢

第二种懒汉模式在多线程中是不安全的,无锁则造成了可能有多个线程同时进入到if里面去


那么在多线程中我们应该如何使用呢?下面推荐一种方案,也是比较实用的方案

public class Test3 {

	public static class Test{
		
		public static Object object = new Object();
		
		private Test(){}
		
		public static Object getObject(){
			return object;
		}
	}
	
	public static Object getObject(){
		return Test.getObject();
	}
}

这种方案利用static 关键字的特点 只用在调用Test3.getObject();的时候才会去初始化构建Test 所以这里做到了启动时间快线程也安全

另外提一下 多线程下懒汉模式的体现

public class Test4 {
	public static Object object = null;
	
	public static synchronized Object getObject(){
		if(object==null){
			object = new Object();
		}
		return object;
	}
}
加锁,所以线程安全了,但是这个锁的粒度有点大,还可以优化一下

我们来看一下双重验证锁,双重验证锁减小了锁的粒度

public class Test5 {
	
	public static Object object = null;
	
	public static Object getObject(){
		if(object==null){
			synchronized (Test5.class) {
				if(object==null){
					object=new Object();
				}
			}
		}
		return object;
	}
}

这个双重验证锁的方式看上去是一个线程安全的,但是博主从一些文章中了解到这个双重验证锁的方式其实也并非线程安全的

这里引用一下从其他博文中拔来的一段话

原文http://www.iteye.com/topic/537563

但是二次检查自身会存在比较隐蔽的问题,查了Peter HaggarDeveloperWorks上的一篇文章,对二次检查的解释非常的详细:

“双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。”

 

其实找到这篇文章之后,我的问题基本上就已经可以解决了,但是看到回帖的同学们也有一些和我一样的问题,还想把这个问题继续梳理一遍。

 

使用二次检查的方法也不是完全安全的,原因是 java 平台内存模型中允许所谓的“无序写入”会导致二次检查失败,所以使用二次检查的想法也行不通了。

 

Peter Haggar在最后提出这样的观点:“无论以何种形式,都不应使用双重检查锁定,因为您不能保证它在任何 JVM 实现上都能顺利运行。”


所以最后总结,在多线程中的单例模式我们尽量采用第一种推荐的方式就好!



  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值