跳至主要內容

并发

chanchaw大约 2 分钟languagejava

DCL中的volatile

名词解释

DCL = double check lock ,双查锁的方式创建单例对象的意思,即在 synchronized 的内外都要有检查对象是否为空的判断,代码如下

volatile01
volatile01

通过双查解决线程不安全的问题,保证单例对象。注意上图中的行号13是否需要使用 volatile 呢? 这里要讲到CPU的指令重排问题,由于CPU的速度比内存的速度快很多,可能出现的情况是CPU发送指令要从内存中获取数据后,数据还没有从内存中返回,CPU就继续执行下面的指令了,这里又要讲到实例化对象时的步骤了。看下面的 java 代码

volatile02
volatile02

位置0是在内存申请了一个区域用于储存实例化来的T 的对象 t 位置4是初始化对象 t 的成员变量为8 位置7是将 t 指向该内存区域 另外由于CPU的运算速度远大于访问内存获取数据的速度,可能会出现一个情况,CPU发送指令要从内存中获取数据,发送完毕之后内存还没有返回来数据,CPU就继续执行下面的代码了,那么在上图中就反应为还没执行位置4的初始化操作就执行位置7的赋予 t 内存地址的操作了。此时由于java的“半初始化”问题, t 中的 m 是0,如果该成员变量保存的是订单数量,原本应该是继续累加1,此时从0开始累加1就导致计数出错了。所以在类内的第一行声明静态实例对象时要使用 volatile 进行阻止指令重排序以保证 java 的半初始化不会出错

volatile 的作用

  • 保持线程可见性
  • 禁止指令重排(乱序执行) 该功能是通过 jvm 的内存屏障功能实现