美文网首页
volatile单例模式

volatile单例模式

作者: 萝卜小青菜丶 | 来源:发表于2019-11-28 16:36 被阅读0次

并发编程有三个重要特性

1.原子性

所谓原子性是指在一次的操作或者多次的操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行。i++不能保证原子性,volatile关键字不保证数据的原子性,synchronized关键字保证
多个原子性操作合在一起就不是原子性操作了
简单的读取和赋值操作是原子性的,将一个变量赋值给另外一个变量的操作不是原子性的
由于synchronized是一种排他机制,因此被他修饰的同步代码是无法被中途打断的,因此其能够保证代码的原子性。

2.可见性

可见性是指当一个线程对共享变量进行了修改,那么另外的线程可以立即看到修改后的最新值
synchronized和Lock保证可见性,他们会在(monitor exit)锁释放之前,会将对变量(共享资源)的修改刷新到主内存中
volatile具有保证可见性的语义

3.有序性

有序性是指程序代码在执行过程中的先后顺序,由于Java在编译器以及运行期的优化,导致了代码的执行顺序未必就是开发者编写代码时的顺序
单利模式中的double-check的写法就是利用了volatile的顺序性

volatile保证了不同线程对共享变量操作时的可见性,也就是说当一个线程修改了volatile修饰的变量,另外一个线程会立即看到最新的值

volatile禁止JVM和处理器对使用volatile修饰的关键字进行指令进行重排序

volatile单例模式

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

上面代码分成三步原子指令:

1、new指令申请内存;
2、在申请的内存中进行Instance的初始化;
3、将申请的内存地址的引用赋值给instance变量;

虽然volatile可以禁止指令重排序, 让上面三个指令有序执行, 但是问题是volatile并不能保证原子性, 所以上面代码中可能出现的问题是当Thread-A执行到第二步进行new Instance初始化时, 此时还没有将地址值赋给instance变量, 所以Thread-B此时看到的instance==null再次进入if中执行new Instance()操作, 但是为instance赋值堆中的引用是原子操作, 所以此时会进行校验instance是否已经被赋值.
所以假设上面代码被两个线程执行, 那么new Instance()会执行两次, 但是instance赋值操作只会执行一次

相关文章

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

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

  • java 安全的单例设计模式之volatile

    通过double-checked locking单例模式 + volatile关键字实现安全的单例设计模式 pri...

  • volatile单例模式

    并发编程有三个重要特性 1.原子性 所谓原子性是指在一次的操作或者多次的操作中,要么所有的操作全部都得到了执行并且...

  • Java单例模式

    单例模式有很多种模式,饿汉,懒汉模式。项目中的单例需要处理多线程,所以选择以下两种实现方式。 关于volatile...

  • Java并发和并行:(二)

    volatile 关键字保证内存可见防止指令重排不保证原子性 volatile 应用,双重检查单例模式 Threa...

  • 单例模式

    一 单例模式的实现方式 DCL双重判定模式(instance 需要设定为 volatile,保证各个线程判断是否存...

  • volatile关键字的作用、原理

    volatile关键字的作用、原理 在只有双重检查锁,没有volatile的懒加载单例模式中,由于指令重排序的问题...

  • 面试回答

    常用设计模式? 一个是单例模式,双重检查模式(volatile),推荐静态内部类 静态代理模式,比较适合能实现相同...

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • 双重校验单例模式的经典实现为什么要加volatile

    双重校验单例模式的经典实现为什么要加volatile 这里加volatile关键字的用途是为了防止指令重排 不加v...

网友评论

      本文标题:volatile单例模式

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