• 单例模式中的双重校验锁


    // 单线程的时候
    class Foo {
        private Helper helper = null;
        public Helper getHelper() {
            if (helper == null) {
                helper = new Helper();
            }
            return helper;
        }
    
    }

    这段在使用多线程的情况下无法正常工作。在多个线程同时调用getHelper()时,必须要获取,否则,这些线程可能同时去创建对象,或者某个线程会得到一个未完全初始化的对象。

    锁可以通过代价很高的同步来获得,就像下面的例子一样。

    //这样写虽然正确,但是粗暴地把getHelper锁住了,这样代价很大
    class Foo {
        private Helper helper = null;
        public synchronized Helper getHelper() {
            if (helper == null) {
                helper = new Helper();
            }
            return helper;
        }
    
    }

    只有getHelper()的第一次调用需要同步创建对象,创建之后getHelper()只是简单的返回成员变量,而这里是无需同步的。 由于同步一个方法会降低100倍或更高的性能[2], 每次调用获取和释放锁的开销似乎是可以避免的:一旦初始化完成,获取和释放锁就显得很不必要。许多程序员一下面这种方式进行优化:

    1. 检查变量是否被初始化(不去获得锁),如果已被初始化立即返回这个变量。
    2. 获取锁
    3. 第二次检查变量是否已经被初始化:如果其他线程曾获取过锁,那么变量已被初始化,返回初始化的变量。
    4. 否则,初始化并返回变量。
    //这种双重检查锁定就很好地解决问题,避免每次调用都要获取锁
    class Foo {
        private Helper helper = null;
        public Helper getHelper() {
            if (helper == null) {
                synchronized(this) {
                    if (helper == null) {
                        helper = new Helper();
                    }
                }
            }
            return helper;
        }
    
    }
  • 相关阅读:
    微信推送给服务器的XML消息解析-springmvc 解析xml数据流
    request.getInputStream() 的两种解析方式
    微信的token验证
    springmvc 解析xml数据
    Spring 定时器 No qualifying bean of type [org.springframework.scheduling.TaskScheduler] is defined
    纯CSS实现图片
    Java线程池应用
    JavaScript 插件的书页翻转效果
    c语言中字符串函数的使用
    窗体显示类
  • 原文地址:https://www.cnblogs.com/diaoniwa/p/7299746.html
Copyright © 2020-2023  润新知