懒汉模式-双重同步锁机制

懒汉模式 是在使用的时候才会生成对象

public class Singleton{
    private static Singleton singleton = null;
    //私有化构造函数,不能从外部生成
    private Singleton(){
    }
    public static Singleton getSingleton(){
        if(singleton == null){
            singleton = new Singleton();
        }
    return singleton;	
    }
}

但是由于在多线程环境下,但A.B两个线程都进入 if(singleton == null),此时有可能会生成两个对象,所以是线程不安全的

网上一般的解决方案是使用双重同步锁机制,例子如下:

public class singleton{
    //私有构造函数
    private singleton{
    }
    
    //单例对象
    private static Singleton instance = null;
    
    //静态的工厂方法
    public static Singleton getInstance(){
        if(instance == null){
             synchronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    
}

虽然加了锁 和双重判断,但是其实这个类是 线程不安全的 

原因是:

这个要从cpu的指令开始说起

当我们执行

instance = new Singleton(); 时 要执行什么操作呢

主要分三步

1.分配对象内存空间 memory = allocate()分配对象内存空间

2.ctorInstance()初始化对象

3.instance = memory 设置instance指向刚分配的内存

但是由于存在指令重排的情况(单线程情况下无影响。多线程下会有影响)

由于2 和3 没有顺序的必然关系

也就可能会出现

1.分配对象内存空间 memory = allocate()分配对象内存空间

3.instance = memory 设置instance指向刚分配的内存

2.ctorInstance()初始化对象

 

此时我们假设有两个线程A和B进入

1.A 先执行了 3.instance = memory 设置instance指向刚分配的内存这个操作,但是还未来得及初始化对象。

2.B 判断 if(instance == null) 时 则会返回true 然后instance, 这时返回值就会出现问题 。

解决方案:

此时使用volatile关键字 则可以解决这个问题 volatile 关键字 有禁止重排序的功能

public class singleton{
    //私有构造函数
    private singleton{
    }
    //单例对象
    private volatile static Singleton instance = null;
    //静态的工厂方法
    public static Singleton getInstance(){
        if(instance == null){
             synchronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    } 
}

 

 

 此时这个类则是线程安全的,当然如果要使用单例模式,推荐使用的还是枚举方法

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值