JVM-DCL单例模式相关的问题

DCL单例模式解决了并发情况下的单例获取

public class Singleton {
    private volatile static Singleton instance = null;
    public  static Singleton getInstance() {
        if(null == instance) {
            synchronized (Singleton.class) {
                if(null == instance) {
                    instance = new Singleton();
                }
            }
        }

        return instance;

    }
}

问题1 :synchronized 之前的非空判断有没有必要?

  不是必要的,但是可以提高效率

问题2 :volatile关键字有没有必要使用?

  必须使用,因为new对象的过程涉及半初始化状态(赋默认值,还没赋初始值),由于操作系统为了提升效率而进行的指令重排操作可能导致某个线程将对象实例刚赋默认值,就被指向了对象,此时instance就不是null了,另一个线程此时过来就会将默认值的对象给读走,与预期的理想效果就不符了,而在生产中,如果这个数据涉及钱,突然被赋值了0,就会造成严重的问题。

  而volatile有两个作用,一个是保证数据的可见性,二是防止被volatile修饰的遍历进行指令重排,也就是被修饰变量的读写操作都是顺序执行的,就不会出现上述问题。

 

tips:最常用的单例模式应该是 构造私有 ,static final 修饰,通过开放方法来获取对象

//单例模式
public
class demo { private static final demo INSTANCE = new demo(); private demo() {}; public static demo getInstance() { return INSTANCE; } }

最安全的单例模式是使用枚举的方法,effective java 作者推荐

 

posted @ 2021-04-15 16:45  karbon  阅读(69)  评论(0)    收藏  举报