美文网首页工作生活
单例模式与线程安全

单例模式与线程安全

作者: Mixqum | 来源:发表于2019-07-04 18:04 被阅读0次

    转载
    http://www.barryzhang.com/archives/521
    https://www.jianshu.com/p/0442fb1e0c7c

    1. double check + volatile单例,保证线程安全
      double check : 指两次if (instance == null)的判断:
    • 外层 if(instance==null)检查,避免每次获取对象锁
    • 内层if(instance==null)检查,锁住对象,避免多线程的时候,对象被创建多个
      原子操作(atomic) : 就是不可分割的操作,在计算机中,就是指不会因为线程调度被打断的操作
      声明并赋值就不是一个原子操作
      // 不是原子操作
      int i = 1; 
    

    指令重排 :计算机为了提高执行效率,会做的一些优化,在不影响最终结果的情况下,可能会对一些语句的执行顺序进行调整

    volatile:其作用是禁止指令重排。因为对象创建的时候在JVM经历3个步骤:
    1.分配内存
    2.调用构造函数,初始化成员变量,创建实例
    3.将实例指向内存
    如果不加volatile,在多线程情况下,1-2-3并不会按顺序执行,比如出现实例非null(执行了1,2),另外一个线程进入第一层check时,拿到的是非空实例,但没有被分配内存(没执行3),导致出现错误(也就是没有被完全初始化就被其他线程使用了)。

    
    /**
     * 演示 double check + volatile单例,保证线程安全
     */
    public class StringUtil {
        // 在多线程环境中,volatile能保证共享变量的可见性以及一定程度的有序性
    
        // volatile关键字的一个作用是禁止指令重排,把instance声明为volatile之后,
        // 对它的写操作就会有一个内存屏障,这样,在它的赋值完成之前,就不用会调用读操作。
        // volatile 阻止的不是singleton = new Singleton()这句话内部[1-2-3]的指令重排,
        // 而是保证了在一个写操作([1-2-3])完成之前,不会调用读操作(if (instance == null))
        private volatile static StringUtil instance;
    
        private StringUtil(){
    
        }
    
        public static StringUtil getInstance(){
            // 先判断是否存在。避免每次获取锁,开销较大
            if(instance==null){
                synchronized (StringUtil.class){
                    // 防止可能出现多个实例的情况
                    if(instance==null){
                        instance = new StringUtil();
                    }
                }
            }
            return instance;
        }
    }
    
    1. 懒汉式单例 + 静态内部类 保证线程安全
      在第一次使用时,实例化对象
    /**
     * 演示 懒汉式单例 + 静态内部类
     */
    public class ToastUtil {
    
        private ToastUtil(){
    
        }
    
        static class  ToastHolder{
            private static ToastUtil instance = new ToastUtil();
        }
    
        public static ToastUtil getInstance(){
            return ToastHolder.instance;
        }
    }
    
    

    相关文章

      网友评论

        本文标题:单例模式与线程安全

        本文链接:https://www.haomeiwen.com/subject/sdgrhctx.html