Double Check形式的单例模式

本文探讨了在Event Bus和Universal Image Loader中常见的Double Check单例模式,强调其减少锁使用并保证线程安全的设计。通过代码示例展示了如何在instance == null的两次检查中避免多个对象的创建,同时解释了volatile关键字在此中的作用,确保对象创建的原子性。尽管某些早期JVM可能不完全支持volatile,但目前主流JVM已解决这一问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这两天在看开源项目时,发现Event Bus和Universalimageloader中写单例模式都是Double Check的形式。平时总是看到各种各样的单例模式,如,饿汉式,懒汉式等等。其中大多存在问题。今天记录一种比较优秀的单例模式的写法------Double Check。以后我准备就用这种方法了。(虽然还有其他优秀的方式,比如内部静态类,枚举)

先上代码:

public class ImageLoader {

	private volatile static ImageLoader instance;

	// Returns singleton class instance
	public static ImageLoader getInstance() {
		if (instance == null) {
			synchronized (ImageLoader.class) {
				if (instance == null) {
					instance = new ImageLoader();
				}
			}
		}
		return instance;
	}
}

这是EventBus中的代码。其中两次检查是否instance == null,第一个是为了避免每次都加锁,毕竟这有一定的开销。第二个是为了避免同步问题,比如十个线程同时调用getInstance()方法,都执行了第一步检查instance == null,并且其中一个线程成功获得了锁(执行了synchronized语句),接下来如果没有再一次判断instance == null,则十个线程将生成10对象,这违背了单例的初衷。

上述代码除了有两次检查instance == null,另一个特点是变量instance的类型声明中添加了volatile,因为像下面这种创建对象的语句并不是原子操作,volatile可以使其成为原子操作,避免同步问题。

instance = new ImageLoader();

虽说部分JVM没有完全volatile,但是目前主流的JVM貌似已经都支持了,所以这个问题一般可以忽略。


参考:

http://www.zhihu.com/question/29971746

https://www.v2ex.com/t/193589#reply15


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值