• Java基础教程:多线程杂谈——双重检查锁与Volatile


    Java基础教程:多线程杂谈——双重检查锁与Volatile

     双重检查锁

      有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化。此时程序员可能会采用延迟初始化。但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题。比如,下面是非线程安全的延迟初始化对象的示例代码:

    public class A{
                private Instance instance;
                public Instance getInstance(){
                    if(instance==null){
                            instance = new Instance();
                        }
                    }
                    return instance;
                }
     }
    

      因为在多线程执行下,instance可能被多次初始化。我们可以对 getInstance() 做同步处理来实现线程安全的延迟初始化。示例代码如下:

    public class A{
                private Instance instance;
                public Instance getInstance(){
                    if(instance==null){
                        synchronized(A.class){
                            if(instance==null)
                               instance = new Instance();
                        }
                    }
                    return instance;
                }
     }
    

      可见,我们用了两次is null 判断,如上则是通过双重检查锁定来降低同步的开销

    问题

      前面的双重检查锁定示例代码(instance = new Singleton();)创建一个对象。这一行代码可以分解为如下的三行伪代码:

    memory = allocate();   //1:分配对象的内存空间 
    ctorInstance(memory);  //2:初始化对象 
    instance = memory;     //3:设置 instance 指向刚分配的内存地址

      上面三行伪代码中的 2 和 3 之间,可能会被重排序(在一些 JIT 编译器上,这种重排序是真实发生的,详情见参考文献 1 的“Out-of-order writes”部分)。2 和 3 之间重排序之后的执行时序如下:

    memory = allocate();   //1:分配对象的内存空间 
    instance = memory;     //3:设置 instance 指向刚分配的内存地址 
                           // 注意,此时对象还没有被初始化!
    ctorInstance(memory);  //2:初始化对象

      所以说可能出现一种情况就是,锁内线程创建对象时仅仅分配了内存地址还未完成初始化,锁外的线程就会判断is null 为false,从而返回一个半成品实例。问题的关键所在就是创建对象并非原子操作,从而被编译器进行指令重排序,导致发生意想不到为问题。

    解决办法

      

      为了防止这个过程的重排序,我们需要将变量设置为volatile类型的变量,volatile的禁止重排序保证了操作的有序性

     

  • 相关阅读:
    C语言中链接影响程序的细节
    Object类的方法
    基于误差反向传播法的神经网络学习的全貌图
    Attention Scaling for Crowd Counting
    plt画图
    机器学习相关技巧
    数值微分
    Noip2017 Day2 T1 奶酪
    串(string)
    八皇后问题
  • 原文地址:https://www.cnblogs.com/MrSaver/p/11350115.html
Copyright © 2020-2023  润新知