并发编程实战之单例模式-双重检查加锁(DCL)

代码:

并发编程实战之单例模式-双重检查加锁(DCL)_第1张图片

 

原理:

并发编程实战之单例模式-双重检查加锁(DCL)_第2张图片

解决方案:

 1、最简单而且安全的解决方法是使用static内部类的思想,它利用的思想是:一个类直到被使用时才被初始化,而类初始化的过程是非并行的,这些都有JLS保证。

如下述代码:

public class Singleton {
 
  private Singleton() {}
 
  // Lazy initialization holder class idiom for static fields
  private static class InstanceHolder {
   private static final Singleton instance = new Singleton();
  }
 
  public static Singleton getSingleton() { 
    return InstanceHolder.instance; 
  }
}

 

    2、另外,可以将instance声明为volatile,即

private volatile static Resource resource; 

   注:

    1、volatile屏蔽指令重排序的语义在JDK1.5中才被完全修复,此前的JDK中及时将变量声明为volatile,也仍然不能完全避免重排序所导致的问题(主要是volatile变量前后的代码仍然存在重排序问题),这点也是在JDK1.5之前的Java中无法安全使用DCL来实现单例模式的原因。

    2、把volatile写和volatile读这两个操作综合起来看,在读线程B读一个volatile变量后,写线程A在写这个volatile变量之前,所有可见的共享变量的值都将立即变得对读线程B可见。

 

   3、 在java5之前对final字段的同步语义和其它变量没有什么区别,在java5中,final变量一旦在构造函数中设置完成(前提是在构造函数中没有泄露this引用),其它线程必定会看到在构造函数中设置的值。而DCL的问题正好在于看到对象的成员变量的默认值,因此我们可以将LazySingleton的someField变量设置成final,这样在java5中就能够正确运行了。

 

你可能感兴趣的:(并发编程)