美文网首页
双重锁单例的不安全性

双重锁单例的不安全性

作者: Wi1ls努力努力再努力 | 来源:发表于2019-04-26 22:59 被阅读0次
public class DoubleCheckedLocking{
  private static Instance instance;
  
  public static Instance getInstance(){
    if( instance == null ){
      synchronized (DoubleCheckedLocking.class){
        if( instance == null){
          instance = new Instance();
        }
      }
    }  
  return instance;
  }
}

这种双重锁单例应该是已经很完美,但是关键在于 new Instance()这句代码,在底层分为 allocation;init;return;即内存分配,初始化,返回内存地址。而在底层会进行重排,重排为内存分配,返回内存地址,初始化(这种重排不违反 intra-thread semantices,能保证的是在同一线程内,初始化 happens-before 使用)。这样会导致 A线程进入后,内存分配,返回内存地址后,在初始化前,B 线程进入,发现 instance 不为 null,则返回使用。此时 instance 还为进行初始化,因此导致的线程不安全。


能完美解决的单例是用用 volatile 禁止初始化和返回的重排或静态内部类单例

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

在多线程环境,volatile 会禁止初始化和返回的重排。

public class SingletonIniti {
        private SingletonIniti() {
        }
        private static class SingletonHolder {
                private static final SingletonIniti INSTANCE = newSingletonIniti();
         }
        public static SingletonIniti getInstance() {
                return SingletonHolder.INSTANCE;
        }
}

因为类的加载和类的初始化在 jvm 内部是由 jvm 保证的线程安全。不允许多个线程同时加载同一个类。同时可能会重排,但是禁止非构造线程看到这种重排。即整个实例化对于非构造线程是透明的。整个实例化作为原子操作在构造线程中。

相关文章

  • 单列模式的多种实现方式

    懒汉模式 饿汉模式 双重同步锁单例模式 volatile+双重同步锁单例模式 静态的工厂方法 枚举

  • 单例模式-Java

    饿汉、懒汉、双重校验锁及其修正、静态内部类、枚举,线程安全性以及原因 单例模式有以下特点: 1、单例类只能有一个实...

  • 枚举来实现单例

    双重校验锁 实现单例: 枚举 实现单例: 上面的双重锁校验的代码很臃肿,是因为大部分代码都是在保证线程安全。为了在...

  • 第03条 用私有构造方法或者枚举类型强化Singleton属性

    单例模式最佳写法1 - 双重校验锁 单例模式最佳写法2 - 静态内部类

  • Java23种设计模式之「单例模式」

    单例模式 之 holder 模式 (推荐) 单例模式 之 饱汉模式(懒汉模式) 单例模式 之 双重锁检查 (Dou...

  • 双重锁单例的不安全性

    这种双重锁单例应该是已经很完美,但是关键在于 new Instance()这句代码,在底层分为 allocatio...

  • 2018-05-14

    单利设计模式 懒汉式 单例模式 饿汉式 单利模式 懒汉式与饿汉式的区别: 双重锁式 单例模式 (DCL )

  • Kotlin 的单例模式

    Kotlin 的单例模式(5种) Kotlin 的5种单例模式: 饿汉式 懒汉式 线程安全的懒汉式 双重校验锁式 ...

  • 项目实战—那些年常用的单例模式

    常见的单例模式:饿汉式、懒汉式、双重检查锁模式、静态内部类实现单例模式、枚举单例模式,本文重点是在项目中如何实现上...

  • Java 常用单例

    一、线程不安全的单例模式 二、线程安全且高效的单例模式 1.双重校验锁 2.静态内部类

网友评论

      本文标题:双重锁单例的不安全性

      本文链接:https://www.haomeiwen.com/subject/cppcnqtx.html