怎么实现一个线程安全的单例模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么实现一个线程安全的单例模式相关的知识,希望对你有一定的参考价值。
设计模式在面试中挺常考的,单例模式是考的最多的。线程安全的单例还有很多种实现方法。可以使用静态内部类、双重校验锁、静态代码块等。
1、饿汉式public class Singleton()
private static Singleton instance = new Singleton();
private Singleton()
public static Singleton getInstance()
return instance;
2、懒汉式
public class Singleton()
private static Singleton instance;
private Singleton()
public static synchronized Singleton getInstance()
if(instance==null)
instance = new Singleton();
return instance;
参考技术A 最简单的办法就是在单例模式所在的类中方法上加同步锁
多线程 实现单例模式 ( 饿汉懒汉 ) 实现线程安全的单例模式 (双重效验锁)
@TOC
单例模式
什么是单例模式
要求我们代码中的某个类,只能有一个实例,不能有多个实例。
实例就是对象。
就是说某个类只能new 一个对象,不能new多个对象。
比如:
单例模式的两种经典实现
单例模式中有两个典型实现:
饿汉模式
懒汉模式
我们来通过一个生活上的例子来给大家讲讲什么是饿汉模式,什么是懒汉模式。
但是在计算机中,普遍认为 懒汉模式 比 饿汉模式好。主要因为 懒汉模式 的效率更高
1. 饿汉模式 (线程安全)
//饿汉模式
class Singleton
// 1、使用 static 创建一个实例,并且立即进行实例化,
private static Singleton instance = new Singleton();
// 2、为了防止程序员在其他地方不小心new这个 Singleton,需要把这个类的构造方法设置为 private
private Singleton();
//3、提供一个方法,让外面能够拿到唯一的实例。
public static Singleton getInstance()
return instance;
分析:
2. 懒汉模式 (线程不安全)
由于比较懒,你让我干活,我才开始,否则我不会主动干的~
说人话就是: 类加载时,不急着初始化对象,第一次调用,初始化对象,后边再次调用,直接返回第一次创建好的对象.
//单例模式 - 懒汉模式
class Singleton2
//1、现在就不是立即初始化实例
private static Singleton2 instance;// 默认值:Null
//2、把构造方法设为 private
private Singleton2();
//3、提供一个公开的方法,来获取这个 单例模式的唯一实例
public static Singleton2 getInstance()
// 只有当我们真正用到这个实例的时候,才会真正去创建这个实例
if(instance == null)
instance = new Singleton2();
return instance;
public class Test20
public static void main(String[] args)
Singleton2 instance = Singleton2.getInstance();
分析:
区别:
其实在计算机很多其它场景中,也会涉及这情况。
一个典型的案例:
实现线程安全的单例模式
1. 懒汉模式+synchronized静态同步方法 (线程安全但效率差)
说到让一个代码线程安全,我们自然而然的就想到加锁!
但是问题就在于:在哪个地方加锁合适呢?
其实也很好观察,将 if 语句的执行操作 给 加锁,使其两个操作为原子性。
直白来说: 就是 if 语句 打包成“一个整体”,就跟前面分析 count++ 一样。
一致性执行完。
加锁范围 一定要包含 if 语句!!!
要不然没有效果,就像下面这样!
本来我们是想将 读 和 写 操作,打包成一个整体,
但是现在只是 针对写操作进行加锁,这时候就跟没加锁 一样,是没有区别的。
请大家注意!并不是代码中有 synchronized,一定就是线程安全的。
这需要看 synchronized 加的位置,也要正确。
所以 synchronized 写的位置。不能随便。
回过头来,我们再来看一下 synchronized 锁的对象写我们应该些什么。
//单例模式 - 懒汉模式
class Singleton2
//1、就不是立即初始化实例
private static volatile Singleton2 instance;// 默认值:Null
//2、把构造方法设为 private
private Singleton2();
//3、提供一个公开的方法,来获取这个 单例模式的唯一实例
public static Singleton2 getInstance()
// 只有当我们真正用到这个实例的时候,才会真正去创建这个实例
synchronized(Singleton2.class)
if(instance == null)
instance = new Singleton2();
return instance;
虽然我们确实通过上述加锁操作,解决了 if 语句 的原子性问题。
2. 懒汉模式+二次判断(双重校验锁,线程安全且效率高)
用法:
class Singleton
private static volatile Singleton instance = null;
private Singleton()
public static Singleton getInstance()
if (instance == null) //第5行
synchronized (Singleton.class) //第6行
if (instance == null) //第7行
instance = new Singleton(); //第8行
return instance; //第9行
分析:
即:
以上是关于怎么实现一个线程安全的单例模式的主要内容,如果未能解决你的问题,请参考以下文章