zoukankan      html  css  js  c++  java
  • 单列模式-双重锁校验解析

    public class Singleton {  
        private volatile static Singleton singleton;  
        private Singleton (){}  
        public static Singleton getSingleton() {  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
            if (singleton == null) {  
                singleton = new Singleton();  
            }  
            }  
        }  
        return singleton;  
        }  
    }  

    这里第一个if,第二个if,synchronized 的本质都是为了避免产生多实例,但侧重点个不相同。

    第一个if判断很好理解,即如果成员变量singleton已经被实例化了,当然不需要重复创建了,直接返回该成员变量即可。

    使用synchronized的目的是保证在多线程环境中,同一时间只有一个线程执行new操作。同时synchronized也可以保证线程可见性,即当当前线程实例化对象之后,其他线程获取锁之后能够感知到上一个线程创建的对象,从而避免重复创建。假设A,B两个线程同时执行 getSingleton() 操作,B线程先获取锁,A线程阻塞。当B线程执行new操作,创建完对象后,释放锁时会立即将 singleton的值刷新回主内存,当A线程拿到锁时,A线程会从主内存中获取最新的的singleton值,此时singleton已经有值了,该值即为B线程创建的对象的地址,所以A线程在执行第二个if判断时恒为false,不会执行new操作。 

    第二个if判断是为了保证在多线程环境中,对象只被new一次,即假如已经有线程创建了对象,则当前线程无需再执行new操作。

    volatile既可以保证线程可见性,也可以防止指令重排序。这里synchronized已经保证了线程可见性,所以这里的volatile主要用来防止指令重排序,因为new操作,赋值操作,return操作不是原子操作,它们执行的顺序可能是乱序的,所以要使用volatile。

    附带一张volatile的原理图       

                                                                                                                                                                                                   

  • 相关阅读:
    Java实现蓝桥杯突击战
    Java实现蓝桥杯突击战
    Java实现蓝桥杯勇者斗恶龙
    Java实现蓝桥杯勇者斗恶龙
    利用cmake来搭建开发环境
    cmake总结
    cmake手册详解----转
    Boost::filesystem 使用小笔记
    Boost学习之可移植路径操作--filesystem
    C++ 檔案、資料夾、路徑處理函式庫:boost::filesystem
  • 原文地址:https://www.cnblogs.com/misterwu/p/14102402.html
Copyright © 2011-2022 走看看