首页 未命名正文

linux编程_双重检查锁定和延迟初始化

云返利网 未命名 2020-05-26 09:05:47 13 0

双重检查锁定的由来

在Java程序中,有时需要推迟一些高开销的工具的初始化操作,而且只有在真正使用到这个工具的时刻,才举行初始化,此时,就需要延迟初始化手艺。
延迟初始化的准确实现是需要一些技巧的,否则容易泛起问题,下面逐一先容。

方案1

public class UnsafeLazyInit{
private static Instance instance;

  public static Instance getInstance(){
    if (instance == null){
         instance = new Instance();
     }
     return instance;
 }
}  

这种做法的错误是很明显的,若是两个线程划分挪用getInstance,由于对共享变量的接见没有做同步,很容易泛起下面两种情形:

1.线程A和B都看到instance没有初始化,于是划分举行了初始化。
2.instance=new Instance操作被重排序,现实执行历程可能是:先分配内存,然后赋值给instance,最后再执行初始化。若是是这样的话,其他线程可能就会读取到尚未初始化完成的instance工具。

方案2

public class UnsafeLazyInit{
private static Instance instance;

public static synchronized Instance getInstance(){
    if (instance == null){
         instance = new Instance();
     }
     return instance;
 }
}

这种做法的问题是很明显的,每一次读取instance都需要同步,可能会对性能发生较大的影响。

方案3

方案3是一个错误的双重检测加锁实现,看代码:

public class UnsafeLazyInit{
private static Instance instance;

public static Instance getInstance(){
    if (instance == null){
         synchronized(UnsafeLazyInit.classs){
             if (instance == null){
                  instance = new Instance();
               }
          }
     }
     return instance;
  }
}

这种方案看似解决了上面两种方案都存在的问题,然则也是有问题的。

问题泉源

instance = new Instance();
这一条语句在现实执行中,可能会被拆分程三条语句,如下:
memory = allocate();
ctorInstance(memory); //2
instance = memory; //3

凭据重排序规则,后两条语句不存在数据依赖,因此是可以举行重排序的。
重排序之后,就意味着,instance域在被赋值了之后,指向的工具可能尚未初始化完成,而instance域是一个静态域,可以被其他线程读取到,那么其他线程就可以读取到尚未初始化完成的instance域。

基于volatile的解决方案

要解决这个设施,只需要克制语句2和语句3举行重排序即可,因此可以使用volatile来修改instance就能做到了。

private volatile static Instance instance;

由于Volatile语义会克制编译器将volatile写之前的操作重排序到volatile之后。

基于类初始化的解决方案

Java语言规范划定,对于每一个类或者接口C ,都有一个唯一的初始化锁LC与之对应,从C到LC的映射,由JVM实现。每个线程在读取一个类的信息时,若是此类尚未初始化,则实验获取LC去初始化,若是获取失败则守候其他线程释放LC。若是能获取到LC,则要判断类的初始化状态,若是是位初始化,则要举行初始化。若是是正在初始化,则要守候其他线程初始化完成,若是是已经初始化,则直接使用此类工具。

public class InstanceFactory{
    private static class InstanceHolder{
        public static Instance = new Instance();
     }
     
    public static Instance getInstance(){
        return InstanceHolder.instance; //这里将导致instance类被初始化
    }    
}

结论

【关于云返利网】

云返利网是阿里云、腾讯云、华为云产品推广返利平台,在各个品牌云产品官网优惠活动之外,云返利网还提供返利。您可以无门槛获得阿里云、华为云、腾讯云所有产品返利,在官网下单后就可以领取,无论是自己用、公司用还是帮客户采购,您个人都可以获得返利。云返利网的目标是让返利更多、更快、更简单!详情咨询13121395187(微信同号)