多线程下的单例模式

相信大家都对单例模式非常熟悉了,可以利用单例模式重复使用某个对象。有一次面试的时候,问到了单例模式,终于明白自己对线程模式下的单例模式不是很了解。饿汉式单例模式是线程安全的,但是它在加载类时就创建实例,不管实例用不用地到,考虑到效率问题,所以个人更喜欢懒汉式单例模式(延迟加载),于是面试题就根据懒汉式单例模式展开。

首先,我们来写一个单线程下的懒汉式单例模式

public class Singleton {
	private static Singleton instance = null;

	private Singleton() {
	}

	public static Singleton getInstance() {
		if (null == instance) {
			instance = new Singleton();
		}
		return instance;
	}
}
这个很简单

Q:写一个多线程下的单例模式

A:balala......

public class Singleton {
	private static Singleton instance = null;

	private Singleton() {
	}

	public static Singleton getInstance() {
		synchronized (this) {
			if (null == instance) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}

Q:为什么同步加在对象上,不加在方法上?

A:因为同步的过程中会持有锁,其他线程在获取锁的过程中需要等待,所以同步粒度越小越好。

以为这个题目很顺利的过去了,没想到悲剧开始上演。

Q:为什么要用同步this?

A:额,好像错了,this无法在类方法使用,那改同步instance。

Q:instance没创建,能持有它的内置锁?

A:好像不行...

Q:如果改成Singleton.class呢?

A:好像是这样

Q:那类锁和对象锁有区别吗?

A:这个我知道,这两个锁无关。持有类锁,别的线程同样可以获取该类的对象锁。

后来,就改成了这样

public class Singleton {
	private static Singleton instance = null;

	private Singleton() {
	}

	public static Singleton getInstance() {
		synchronized (Singleton.class) {
			if (null == instance) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}
A:如果我不想每次都去获取锁,再判断实例是否为空呢?每次获取类锁,会导致性能一定的下降

Q:可以使用双检锁。

public class Singleton{
	private static Singleton instance = null;
	
	private Singleton(){
	}
	
	public static Singleton getInstance(){
		if(null == instance){
			synchronized(Singleton.class){
				if(null == instance){
					instance =  new Singleton();
				}
			}
		}
		return instance;
	}
}

Q:不过双检锁有一个问题,就是对象在初始化的时候,有两步,第一步,系统默认值的初始化,第二步才是构造方法初始化。在系统默认值初始化完毕以后,实例instance不为null,另外的线程可能会直接发现instance不为null,继续执行后面的代码,但是实际上instance通过构造方法做的初始化还没执行,在多线程里,这叫不正确的发布对象。可以这样做。

public class Singleton{
	private static Singleton instance = null;
	
	private Singleton(){
	}
	
	public static Singleton getInstance(){
		if(null == instance){
			synchronized(Singleton.class){
				if(null == instance){
					Singleton temp =  new Singleton();
					instance = temp;
				}
			}
		}
		return instance;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值