zoukankan      html  css  js  c++  java
  • 从简单示例看对象的创建过程, 为什么双重检查的单例模式,分析Volatile关键字不能少

    编译指令 :javac Test.java
    反编译指令: javap -v Test

    代码

    public class ObjectTest {
        int m = 8;
    
        public static void main(String[] args) {
            ObjectTest o = new ObjectTest();
        }
    }
    

    安装jclasslib插件后,可以看到这个类的clazz文件: 如图所示:

    这个是 对象的创建过程, 这个过程中有个半初始化状态, 这里的 invokespecial 和 astore_1 这二条指令会发生指令重排,
    比如一个 双重检查的单例模式:

    class Singleton {
        private Singleton() {
        }
    
        private volatile static Singleton INSTANCE;//这里没有使用 volatile 关键字
    
        public static Singleton getInstance() {
            if (INSTANCE == null) {  //第1行
                synchronized (Singleton.class) {  //第2行
                    if (INSTANCE == null) {  //第三行
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        INSTANCE = new Singleton(); //第四行
                    }
                }
            }
            return INSTANCE;
        }
    
        public static void main(String[] args) {
            for (int i = 0; i < 1000; i++) {
                new Thread(()->{System.out.println(Singleton.getInstance().hashCode());}).start();
    
            }
        }
    }
    

    如果 没有volatile关键字,那么在 INSTANCE = new Singleton();这一行代码,new对象的时候,对应的clazz文件的 invokespecial 和 astore_1 这二条指令就有可能会发生指令重排,
    先new了对象,此时对象创建处于半初始状态, 先执行了astore_1 建立了关联,后执行了 invokespecial, 就会导致, 第一行判断INSTANCE == null, 此时加锁,接下来判断 INSTANCE 为半初始化状态,并不为null, 那么这个单例模式就会失败
    所以 这种双重检查的单例模式, volatile关键字不能少

  • 相关阅读:
    2017沈阳站 Tree
    P2146 [NOI2015]软件包管理器
    hdu3307 欧拉函数
    poj 3126 Prime Path bfs
    CSL的字符串
    P1045 麦森数
    洛谷 P1338 末日的传说
    树链剖分
    SQL[Err] ORA-00933: SQL command not properly ended
    Postman 快速入门之脚本
  • 原文地址:https://www.cnblogs.com/lvcai/p/13754666.html
Copyright © 2011-2022 走看看