java多线程单例模式(懒汉模式,饿汉模式)

java多线程单例模式(懒汉模式,饿汉模式)

单例模式
单例对象的类只能允许一个实例存在。

特征
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
饿汉模式
在类加载时,完成实例化,用时直接用。可避免线程同步问题。

public class singleTon {
private static final singleTon instance =new singleTon();
private singleTon(){ }
public static singleTon getInstance(){
return instance;
}
}

优点
线程安全

缺点
生命周期较长,造成资源浪费

在类装载的时候就完成实例化,没有达到懒加载的效果。如果从始至终从未使用过或最后才用到这个实例,则会造成内存资源的浪费。

懒汉模式
类加载时,先不实例化,等到用到时再加载。

public class SingleTon {
private static SingleTon instance=null;
private SingleTon(){}
public static SingleTon getInstance(){
if (instance==null){
//用到了,开始实例化
instance=new SingleTon4();
}
return instance;
}
}

但这个方式是线程不安全的,需要加锁!

public class SingleTon {
private static SingleTon instance=null;
private SingleTon(){}
public static SingleTon getInstance(){
synchronized (SingleTon.class) {
if (instance==null){
//用到了,开始实例化
instance=new SingleTon();
}
}
return instance;
}
}

这里的赋值操作不具有原子性。new 对象实际上是拆分成三个步骤:

1.分配内存 2.执行初始化 3.赋值给变量。

还效率低、资源浪费,每个线程都要先来竞争锁,竞争失败就阻塞。竞争成功了也不知道这instance到底还是不是null,反正现在看着是null,那我就去实例!
不好不好!那怎么办呢?
双重校验锁

public class SingleTon4 {
//volatile保证共享变量可见性
private static volatile SingleTon instance=null;
private SingleTon(){}
public static SingleTon getInstance(){
//双重判断:防止多次实例化
if (instance==null) {
synchronized (SingleTon.class) {
if (instance == null) {
//synchronized加锁:保证赋值操作原子性
instance = new SingleTon();
}
}
}
return instance;
}
}

可见性
一个线程修改了共享变量,其他线程会立刻看到修改后的新值。
在多线程执行中,原本是要将数据从主内存拿到自己的私有工作区中去修改,然后再放回主内存中,但这个过程中,可能A线程正在改数据还没放回去,B线程又去拷贝这个数据去修改,导致数据不一致。
使用volatile关键字,可以让线程们每次都去主存中读取,用完再刷新到主存。

因此,在本例中,第一重判断就限制了很多线程,线程们一看instance已经被实例了,就不会再去竞争锁了,因为共享数据可见,就直接去读取结果并返回。

JVM在执行代码过程中为了优化性能,会有指令重排序的特性。如实例化对象时的三步可能会重排序:
原本:1.分配内存空间 2.初始化 3.赋值给变量
可能顺序被优化为:1–3—2
当1、3执行完后,对方发现变量不为null,就直接返回了,实际上该变量还没初始化完,引用里保存的是无效对象。

静态内部类
一个集 饿汉模式和懒汉模式 优点于一身的方法

class SingleTon3 {
private SingleTon3(){}
private static class Holder{
static SingleTon3 instance=new SingleTon3();
}
public static SingleTon3 getInstance(){
return Holder.instance;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值