zoukankan      html  css  js  c++  java
  • 对Java单例模式 volatile关键字作用的理解

      单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课。其中最经典的一种写法是:

    class Singleton {
        private volatile static Singleton instance;//volatile关键字防止指令重排
        private Singleton(){}
        public static Singleton getInstance() {
            if ( instance == null ) { //一重判断
                synchronized (Singleton.class) {//对Singleton.class上锁
                    if ( instance == null ) {//二重判断
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

      其中有两个关键的地方:1,初始化instance实例的时候,采用两重判断对Singleton.class上锁。

                 2,静态变量instance使用了volatile关键字进行修饰。

      第一个问题相对比较好理解  

            if ( instance == null ) { //一重判断
                synchronized (Singleton.class) {//对Singleton.class上锁
                    if ( instance == null ) {//二重判断
                        instance = new Singleton();
                    }
                }
            }

      

      sychronized关键字锁住Singleton类而不是instance对象,是因为,此时instance为空,加sychronized没有意义。
    第一重判断的意义在于:如果instance非空,就跳过了锁的步骤,减少加锁的资源开销。但是由于第一重判断在代码锁之外,如果不同线程同时访问到install==null,会先后阻塞执行代码锁内的内容。所以在代码锁内加第二重判断就很有必要了,避免第一个线程获取实例后,第二个线程获得资源锁又执行了一次instance的初始化,产生两个不同的实例。

      很多人不理解instance实例在声明时加volatile关键字的作用,或者是发现别人这么写了,自己也跟着这么写。对volatile关键字的解释,很多地方只是提了句“当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,它可以防止指令重排”,这里不想对这句话进行展开解释,想详细了解可以参考文章
      https://www.cnblogs.com/shan1393/p/8999683.html
      https://www.cnblogs.com/xrq730/p/7048693.html

      instance = new Singleton()看上去只有一句话,但java的初始化成员变量包括内存分配、初始化、返回对象在堆上的引用等一系列操作。对于synchronized代码块内,一条语句完整执行是没有问题的。但如果发生了指令重排,先返回对象在堆上的引用,再进行初始化。对于另一个执行到一重判断的线程来说,由于instance已经指向了堆上的一段内存空间,那么instance就不为空,会将未完成初始化的对象返回给其他函数调用,引发一系列不安全隐患。加了volatile关键字,可以保证返回对象在对上的引用发生在初始化之后,避免了这种情况的发生。这就是单例模式下 instance加volatile关键字的作用。

  • 相关阅读:
    C++ Primer Plus 第15章 友元、异常和其它
    03013_JDBC工具类
    python GUI编程(Tkinter)
    Python2.x与3​​.x版本区别
    【python教程】Python JSON
    【python教程】Python IDE
    通过Google Custom Search API 进行站内搜索
    支持wmv、mpg、mov、avi格式的网页视频播放代码
    编写更好的jQuery代码的建议
    KindEditor得不到textarea值的解决方法
  • 原文地址:https://www.cnblogs.com/acesui/p/9557501.html
Copyright © 2011-2022 走看看