b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

编写线程安全的单例模式

电脑杂谈  发布时间:2020-07-11 23:17:26  来源:网络整理

线程安全的单例模式 c_单例模式 c++_写一个线程安全的单例模式

摘自Jark博客,有人认为使用volatile的原因是可见性,这意味着它可以确保线程在本地没有实例的副本,并且每次都从主内存中读取它. 但这实际上是错误的. 使用volatile的主要原因是另一个功能: 禁止指令重新排序优化. 也就是说,在易失变量的赋值操作之后,将有一个存储屏障(在生成的汇编代码上),并且在该存储屏障之前不会对读取操作进行重新排序. 例如,在上面的示例中,必须在1-2-3或1-3-2之后执行获取操作,并且不存在执行1-3然后获得值的情况. 从“优先发生原理”的角度来看,这意味着易失性变量的写操作发生在变量的读操作之前(这里的“后退”是按时间顺序排列的).

但是请特别注意以下事实: 在Java 5之前的版本中使用易失性双重检查锁仍然存在问题. 原因是Java 5之前的JMM(Java内存模型)存在缺陷. 即使将变量声明为volatile,也无法完全避免重新排序. 主要原因是volatile变量之前和之后的代码仍然存在重新排序问题. 易失性屏蔽重新排序的问题仅在Java 5中得以解决,因此您以后可以放心使用volatile.

接下来,看一个更简单的线程安全单例模式:

class Singleton{
    private static final Singleton INSTANCE = new Singleton();
    private Singleton(){}
    public Singleton getInstance(){
        return INSTANCE;
    }
}

单例模式 c++_写一个线程安全的单例模式_线程安全的单例模式 c

由于实例被声明为静态变量和最终变量,因此它将在第一次加载类时在内存中初始化,因此创建实例本身是线程安全的. 这也是因为对象是在类加载期间创建的,因此图像称为“饥饿的人”.

但是他的缺点也很明显,因为即使客户端未调用此方法,该类的实例也已创建,这在一定程度上也造成资源浪费. 同时,他不能在某些使用情况下使用它: 例如,实例的创建取决于参数或配置文件. 在getInstance之前写一个线程安全的单例模式,必须调用一个方法来为其设置参数,然后才能使用此单例模式.

这一次(当当当当!!),我们应该使用我们的把戏-静态内部类.

public class Singleton {  
    private static class SingletonCreater{
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton(){}
    public static final Singleton getInstance(){
        return SingletonCreater.INSTANCE;
    }
}

单例模式 c++_写一个线程安全的单例模式_线程安全的单例模式 c

为什么静态内部类可以实现线程安全的调用?首先看一下内部类加载的时间:

1. 调用外部类的静态变量和静态方法可以将外部类加载到内存中,但不会加载被调用外部类的内部类(无论是否为静态).

2. 在加载静态内部类之前,将首先加载外部类. 静态内部类或非静态内部类仅在使用其成员时加载.

3. 内部类可以自由使用外部类的成员对象和方法(甚至是私有的),而无需生成外部类对象

单例模式 c++_写一个线程安全的单例模式_线程安全的单例模式 c

然后写一个线程安全的单例模式,当线程调用getInstance方法时,因为调用了静态内部类的成员,所以将内部类加载到内存中,并且此时也将内部类的成员加载并初始化,因此返回是外部类Too的实例. 这种编写方法仍然使用JVM自己的机制来确保线程安全. 由于SingletonHolder是私有的,因此除了getInstance()之外没有其他方法可以访问它,因此它很懒. 同时,在读取实例时它不会同步. 性能缺陷;也不依赖于JDK版本.

有没有更简单的实现?一些! ! ! !枚举!

public enum EasySingleton{
    INSTANCE;
}

超级简单吗? ! ! !由于创建枚举类的实例的过程是线程安全的,因此我们可以使用EasySingleton.INSTANCE来调用该实例.

单例模式 c++_线程安全的单例模式 c_写一个线程安全的单例模式

顺便说一句,回顾一下枚举

枚举格式:

//只有枚举项的枚举类
public enum 枚举类名 {
    枚举项1,枚举项2,枚举项3…;
}

这里的每个枚举项都是枚举类的实例,或者您可以编写带有参数的枚举类型:

public enum 枚举类名 {
    枚举项1("100-90"),枚举项2("90-80"),举项3("80-70")...;
    String value;
    枚举类名(String str){    //构造方法
        this.value = str;
    }
}

使用抽象方法进行枚举: 创建枚举对象时实现抽象方法

public enum 枚举类名 {
    枚举项1("100-90"){
        public String localValue(){
            return "优秀";
        }
    },枚举项2("90-80"){
        ...
    },枚举项3("80-70"){
        ...
    };
    String value;
    枚举类名(String str){    //构造方法
        this.value = str;
    }
    public abstract String localValue();
}

有关枚举的更多知识: 单击此处


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-276998-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...