volatile 的 随笔录

前面讲java关键字synchronized,我们知道在java中还有一大神器就是关键volatile,可以说是和synchronized各领风骚,其中奥妙。

synchronized 是阻塞式的同步,在线程竞争激烈的情况下回升级成为重量级锁。而volatile就可以说是java虚拟机提供的最轻量级的同步机制。

    线程对 volatile 变量的修改会立刻被其他线程锁感知,既不会出现数据脏读的现象,从而保证了数据的“可见性” ! 被 volatile 修饰的变量能够保证没个线程能够获取变量的最新值,从而避免了数据脏读现象。

我们都知道在java 内存模型中,线程对数据的操作 ,不会直接去访问 主内存的 而是将 主内存的共享变量 “拷贝”

一份到 工作内存中  也就是说 主内存被所有线程共享,存放着 共享变量的“本尊”,而工作内存存储着共享变量的 “副本”。

线程对 共享变量的所有操作都必须在工作内存中进行,不能直接读写主内存中的变量,不同的线程之间也无法访问 彼此的工作内存,变量值的传递只能通过主内存来进行。

解释下 可见性

 由于线程对共享变量的更改不会立刻同步到主内存中,而被volatile 修饰的变量。当一个线程修改了变量的值,新的值会立刻同步到主内存中去 ,这样就保证了不会出现脏读现象的发生。

 为什么 volatile 关键字可以有这样的特向呢? 

    这得益于 java 语言的先行发生原则 【happens-before】

 volatile 只能保证变量的 可见性,并不能保证变量的原则性。

     在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。为了性能,一个线程会在自己的memory中保持要访问的变量的副本。这样就会出现同一个变 量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况。 一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。

volatile 对 指令重排的影响?

       指令重排? 

           是指jvm 在编译java 代码的时候或者 cpu 在执行 jvm 字节码的时候,对现有的指令顺序进行重新排序。

    其目的是:

    为了在不改变程序执行结果的前提下,优化程序的运行效率。【在这里所说的不改变执行结果,指的是不改变单线程下的程序执行结果】

为了解决指令重排就产生了 内存屏障

内存屏障共分为四种类型:

LoadLoad屏障

抽象场景:Load1; LoadLoad; Load2

Load1 和 Load2 代表两条读取指令。在Load2要读取的数据被访问前,保证Load1要读取的数据被读取完毕。

 

StoreStore屏障:

抽象场景:Store1; StoreStore; Store2

Store1 和 Store2代表两条写入指令。在Store2写入执行前,保证Store1的写入操作对其它处理器可见

 

LoadStore屏障:

抽象场景:Load1; LoadStore; Store2

在Store2被写入前,保证Load1要读取的数据被读取完毕。

 

StoreLoad屏障:

抽象场景:Store1; StoreLoad; Load2

在Load2读取操作执行前,保证Store1的写入对所有处理器可见。StoreLoad屏障的开销是四种屏障中最大的。

是不是感觉这些 内存屏障很抽象啊,其实我觉得

volatile做了什么?

  在一个变量被 volatile 修饰后 ,jvm 会 为我 们做两件事:

1. 在每个 volatile 写操作之前 插入 StoreStore屏障,在写操作后插入 StoreLoad 屏障

2. 在每个volatile 读操作之前插入 LoadLoad 屏障,在读操作之后插入LoadStore屏障

从而阻止指令的重排序了。

内存屏障和 happends-before 之间有什么的联系呢?

  happends-before[先行发生原则】 是 JSR-133 的规范之一;内存屏障是cpu 的指令,可以简单 认为前者是最终的目的,后者是实现的手段吧。

总结: volatile  有 两大特性

1. 保证变量在线程之间的可见性。 可见性是基于 cpu 的内存屏障指令,被 jsr-133  抽象为 happends-before 原则

2. 阻止编译时和运行期的指令重排。编译时 jvm 编译器遵循 内存屏障的约束,运行时依靠cpu内存屏障 指令来阻止重排.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值