zoukankan      html  css  js  c++  java
  • 单例模式

    public class DoubleLock{

    //如果此处不加volatile,当线程A执行到"  doubleLock = new DoubleLock(); "这一行,而线程B执行到外层的"if (singleton == null) "时,可能出现instance还未完成构造,

    //但是此时不为null导致线程B获取到一个不完整的instance。

    //之所以会出现这种情况,是因为JVM的指令重排序。

        private static volatile DoubleLock doubleLock = null;//volatile防止指令重排序(很重要,不加会造成拿到初始化不完全的实例),内存可见(缓存中的变化及时刷到主存,并且其他的内存失效,必须从主存获取)

        private DoubleLock(){

            //构造器必须私有  不然直接new就可以创建

        }

        public static DoubleLock getInstance(){

            //第一次判断,假设会有好多线程,如果doubleLock没有被实例化,那么就会到下一步获取锁,只有一个能获取到,

            //如果已经实例化,那么直接返回了,减少除了初始化时之外的所有锁获取等待过程

            if(doubleLock == null){

                synchronized (DoubleLock.class){ //这个DoubleLock是public class Singleton这个类名

                    //第二次判断是因为假设有两个线程A、B,两个同时通过了第一个if,然后A获取了锁,进入然后判断doubleLock是null,他就实例化了doubleLock,然后他出了锁,

                    //这时候线程B经过等待A释放的锁,B获取锁了,如果没有第二个判断,那么他还是会去new DoubleLock(),再创建一个实例,所以为了防止这种情况,需要第二次判断

                    if(doubleLock == null){

                        //下面这句代码其实分为三步:

                        //1.开辟内存分配给这个对象

                        //2.初始化对象

                        //3.将内存地址赋给虚拟机栈内存中的doubleLock变量

                        //注意上面这三步,第2步和第3步的顺序是随机的,这是计算机指令重排序的问题

                        //假设有两个线程,其中一个线程执行下面这行代码,如果第三步先执行了,就会把没有初始化的内存赋值给doubleLock

                        //然后恰好这时候有另一个线程执行了第一个判断if(doubleLock == null),然后就会发现doubleLock指向了一个内存地址

                        //这另一个线程就直接返回了这个没有初始化的内存,所以要防止第2步和第3步重排序 所以在开头加了volatile

                        doubleLock = new DoubleLock();

                    }

                }

            }

            return doubleLock;

        }

    }

  • 相关阅读:
    Python匿名函数详解
    python开发 -- 经常浏览的网站
    Python -- 变量指向
    我的Python开发之路---微信网页授权(扫码登陆)
    信息收集篇:玩转信息收集(一)
    TodoList:适合初学者的vue+node小项目
    节流和防抖的实现
    javascript的this问题
    bind、call、apply的区别与实现
    杜教筛
  • 原文地址:https://www.cnblogs.com/wl889490/p/12639412.html
Copyright © 2011-2022 走看看