singleton(2)

接上篇:
主要讨论的是线程的安全问题。

饿汉式是直接存在的一份对象,所以说是线程安全的,大家每次都会共享同一个对象。而懒汉式中:

问题场景:线程A,线程B
由于我们是要new对象的,如果两个线程在刚刚碰巧的时候,会有一种情况就是:线程A在new对象的时候,纯种B也刚好判断到了m==null这句,这个时候,m是不存在的,于是线程A创建了一个新的对象,线程B也进来了创建一个新的m对象,这样内存中就存在了两个同样的ConfigModel,就不再是单例模式了,也就是所说的线程安全。


这个时候,我们就需要加锁,用关键字synchronized来给方法加锁
public synchronized static ConfigModel1 getInstance() {
    if(m == null) {
    m = new ConfigModel1();
    return m;
    }
    return m;
}

这样就能保证线程的同步安全,可是问题又来了,既然有加锁,就会有队例排除,如果队伍很长的时候,我们每个线程都在排队判断的话,这样太浪费时间了,于是可以如此做:
private volatile static ConfigModel1 m = null;定义成如此,用volatile关键字定义,它意思是,被其修饰的变量不会被本地线程缓存。
同时修改getInstance
//双重检查加锁机制
public static ConfigModel1 getInstance() {
if(m == null) {
synchronized(ConfigModel1.class) {
if(m == null) {
m = new ConfigModel1();
return m;
}
}
}
return m;
}

将方法同步改成代码块的同步,先判断是否存在的时候再去同步,这样的初始化只有一次,大大的节省了时间,性能几乎不受到影响。
但是由于volatile这个关键字会屏蔽掉虚拟机中的必要的代码优化,会影响部分性能,所以并不十分推荐使用这种。

缓存的思想:
缓存也就是在内存中的一份拷贝,我们可以使用懒汉式延迟加载的思想去实现缓存,缓存一般是由map实现,多说一点,单例模式里只是产生一个对象,如果我们要多上对象的时候呢,比如要四个对象,这个时候,我们就可以用map来实现,map里产生4个对象,对应4个key,在什么时候用哪个对象,什么时候释放掉,这就又牵到对象调试的问题,不是本节所要介绍,后来再研究吧。

更优的单例模式,可以使用内部类来实现,根据内部类的特性,即保证线程的安全,又保证单例。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值