今天发现对以往学习的单例模式掌握不够深入,特别是多线程下的线程安全问题,于是学习了高并发下如何保证单例模式的线程安全性。
单例模式的概念:单例模式是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种模式方法。
从概念中体现出了单例的一些特点:
在任何情况下,单例类永远只有一个实例存在
单例需要有能力为整个系统提供这一唯一实例
两种最基本的单例实现
一、饿汉式(线程安全)
饿汉式单例是指在方法调用前,实例就已经创建好了。
|
|
饿汉式多线程并发测试
多线程执行方法如下:
|
|
测试结果和结论
从运行结果可以看出实例变量额hashCode值一致,这说明对象是同一个,饿汉式单例是线程安全的。
|
|
二、懒汉式(线程不安全)
懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。
|
|
懒汉式多线程并发测试
首先稍微修改代码,让线程当前暂时休眠,然后执行上面饿汉式的多线程调用方法。
|
|
测试结果和结论
从这里执行结果可以看出,单例的线程安全性并没有得到保证.
|
|
线程安全的懒汉式单例
要保证线程安全,我们就得需要使用同步锁机制,下面就来看看我们如何一步步的解决 存在线程安全问题的懒汉式单例。
一、使用synchronized关键字
出现非线程安全问题,是由于多个线程可以同时进入getInstance()方法,那么只需要对该方法进行synchronized的锁同步即可:
|
|
然后执行MyThread测试方法。
测试结果和结论
从执行结果上来看,问题已经解决了,但是这种实现方式的运行效率会很低。同步方法效率低,那我们考虑使用同步代码块来实现。
|
|
二、使用同步代码块
|
|
这里的实现能够保证多线程并发下的线程安全性,但是这样的实现将全部的代码都被锁上了,同样的效率很低下。
三、使用Double Check Locking 双检查锁机制(推荐)
为了达到线程安全,又能提高代码执行效率,我们这里可以采用DCL的双检查锁机制来完成,代码实现如下。
|
|
测试结果及结论
使用了volatile关键字来保证其线程间的可见性;在同步代码块中使用二次检查,以保证其不被重复实例化。集合其二者,这种实现方式既保证了其高效性,也保证了其线程安全性。
|
|