java进阶(4)之volatile关键字深入详解

volatile作用

可见性

当有多个线程共用一个变量,有线程读,有线程写,那么就有可能导致有的线程无法及时读取到另外线程修改后的变量的值。volatile关键字可以让其他线程立即看到变量的最新值。

有序性

终端设备为了加快运行速度,会让编译器和处理器进行指令重排序,有可能会导致上下两句代码的执行顺序不一致。volatile关键字看可以禁止指令重排序,保证代码语句按顺序执行。

CPU多级缓存模型

CPU缓存模型

现代的计算机技术,内存的读写速度没什么突破,CPU如果要频繁的读写内存的话,会导致性能较差,计算性能就会低。所以,给CPU加了几层缓存,CPU可以直接操作自己对应的高速缓存,不需要直接频繁地跟主内存通信,从而保证CPU的计算效率,如图所示:
在这里插入图片描述

默认CPU缓存模型带来的问题

当多线程并发运行的时候,有可能导致各个CPU的本地缓存,跟主内存没有同步,同一个共享变量,在不同线程里可能都不一样,如图所示:
在这里插入图片描述

CPU窥探机制和缓存一致性

“窥探”背后的基本思想是,所有内存传输都发生在一条共享的总线上,而所有的处理器都能看到这条总线:缓存本身是独立的,但是内存是共享资源,所有的内存访问都要经过仲裁(arbitrate):同一个指令周期中,只有一个缓存可以读写内存。窥探协议的思想是,缓存不仅仅在做内存传输的时候才和总线打交道,而是不停地在窥探总线上发生的数据交换,跟踪其他缓存在做什么。所以当一个缓存代表它所属的处理器去读写内存时,其他处理器都会得到通知,它们以此来使自己的缓存保持同步。只要某个处理器一写内存,其他处理器马上就知道这块内存在它们自己的缓存中对应的段已经失效。

java内存模型

java内存模型图解

在这里插入图片描述
java内存模型跟cpu缓存模型是类似的,基于cpu缓存模型来建立的java内存模型,只是java内存模型屏蔽了底层计算机带来的差异化问题。

  • read 从主内存读取
  • load 将主内存读取到的值写入到工作内存
  • use 从工作内存读取数据来计算
  • assign将计算好的值重新赋值到工作内存中
  • store 将工作内存数据写入到主内存
  • write 将store过去的变量值赋值给主内存中的变量

并发编程三大特性

特性介绍

可见性

俩线程共享一个变量,在一个线程修改了此变量,在另外一线程能立马感知到。

有序性

编译器和处理器有时候为了提高代码执行效率,会将指令重排序,导致部分代码没法按照顺序执行。

原子性

在俩线程同时对共享整型变量index执行index++操作,完了之后立即获取的值可能只是获取到一次++的值。
在这里插入图片描述

volatile为啥无法保证原子性?

在这里插入图片描述
如果所示,俩线程共享一个变量index,同时对index进行index++,虽然俩线程同时可以感知到另外一线程修改了index,但是却有可能无法在另一线程+1的基础上,再进行++操作。

volatile底层实现原理

lock指令

被volatile修饰的变量,执行写操作的话,JVM会发送一条lock前缀给CPU,CPU在计算完了之后会立即将这个值写回主内存,同时因为有MESI缓存一致性协议,所以会对总线进行无限循环窥探,验证自己本地缓存中的数据是否被别人修改。
如果发现别人修改了某个缓存的数据,那么CPU就会将自己本地缓存的数据过期掉,然后这个CPU上执行的线程在读取那个共享变量的时候,就会从主内存重新加载最新的数据了。

内存屏障:禁止重排序

上面说了,编译器和处理器有时候为了加快处理效率,会将指令进行重排序,导致代码中上下俩语句执行顺序不一致,而在java中使用volatile就不会进行指令重排。
每个volatile写操作前面,加StoreStore屏障,禁止上面的普通写和他重排;
每个volatile写操作后面,加StoreLoad屏障,禁止跟下面的volatile读/写重排;
每个volatile读操作前面,加LoadLoad屏障,禁止上面的普通读和volatile读重排;
每个volatile读操作后面,加LoadStore屏障,禁止下面的普通写和volatile读重排。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值