java多线程开发01——volatile

java多线程开发01——volatile

volatile

一但一个共享变量(类成员变量,类静态成员变量) 被volatile修饰后那么就具备了以下两层语义
(1)保证不同线程对其的可见性,即不同线程修改该变量,新值对于其他线程是立即可见的。
(2)禁止指令重排序。

可见性

所谓可见性,是指某个线程对volatile修饰的变量进行修改,其他线程可见修改后的内容。基于以下两点实现这个功能:

  1. 将当前处理器缓存行的数据写回到系统内存。在java内存模型中,有个统一的主存,保存所有的共享变量。然后每个线程都有自己的工作内存,每个线程把共享变量拷贝到工作内存中进行运算。运算后的值什么时候写回主存,这个时间是不确定的。对经过volatile修饰的变量执行写入操作,处理器会把把值写回主存中。这个过程通过一个Lock指令实现:Local前缀的指令在多核处理器下会引发两件事情:
    1. 当前处理器缓存行的数据写回到系统内存
    2. 这个写回内存的操作会使其他CPU里缓存该地址的数据无效
  2. 这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。CPU嗅探总线,当volatile修饰的变量发生改变的时候,会从主存中重新读取对应的变量。

MESI(缓存一致性协议)
当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。
至于是怎么发现数据是否失效呢?
嗅探
每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。

禁止指令重排序

为了提高性能,编译器和处理器常常会对既定的代码执行顺序进行指令重排序。

一个好的内存模型实际上会放松对处理器和编译器规则的束缚,也就是说软件技术和硬件技术都为同一个目标,而进行奋斗:在不改变程序执行结果的前提下,尽可能提高执行效率。

JMM对底层尽量减少约束,使其能够发挥自身优势。

因此,在执行程序时,为了提高性能,编译器和处理器常常会对指令进行重排序。

一般重排序可以分为如下三种:

  • 编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;
  • 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;
  • 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行的。

volatile关键字禁止指令重排序有两层意思

  1. 当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
  2. 在进行指令优化时,不能把volatile变量后面的语句放到其前面执行。也不能把volatile变量前面的语句放在其后面执行。

即:

  • 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存
  • 当读一个volatile变量时,JMM会把该线程对应本地内存置为无效,线程接下来将从内存中读取共享变量

那Volatile是怎么保证不会被执行重排序的呢?

内存屏障

java编译器会在生成指令系列时在适当的位置会插入内存屏障指令来禁止特定类型的处理器重排序。

为了实现volatile的内存语义,JMM会限制特定类型的编译器和处理器重排序,JMM会针对编译器制定volatile重排序规则表:

需要注意的是:volatile写是在前面和后面分别插入内存屏障,而volatile读操作是在后面插入两个内存屏障。

:在volatile写操作发生之前,使用storestore保证之前的普通写操作都对任意处理器可见了。这是因为StoreStore保障普通写在vo写之前刷到主内存。在volatile写操作发生之后插入了StoreLoad屏障。此屏障作用是避免volatile写于后面有可能的volatile读/写重排序

volatile写

:LoadLoad屏障用来禁止处理器把上面的volatile读和普通读重排序,LoadStore屏障用来禁止处理器把上面的volatile读与下面的普通写重排序

volatile读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值