第二课 Volatile关键字
- 谈谈对volatile的理解
Volatile是java虚拟机提供的轻量级同步机制
- Volatile特性
- 保证可见性
保证内存可见性,其实就是JMM基本特性之一,线程一般无法操作主存,
这里就要只要一个概念就是缓存一致性,Volatile可以保证内存可见性就是通过缓存一致性协议完成的(MESI协议),
这里介绍一下什么是MESI协议:
在早期的CPU中,是通过在总线加LOCK锁的方式实现的,但是这种方式开销太大,所以Intel开发了缓存一致性协议,也就是MESI协议。缓存一致性协议呢就是当CPU写数据时候,如果发现操作的变量是共享变量,什么意思呢这里就是说很多线程都用到该变量,比如线程t1和t2都用到了一个信号 int start 那么start就是俩个线程的共享变量,这里当发出写信号时候就会发信号给CPU该变量的内存地址无效了,如果其他线程想拿到这个变量,那么必须从主存里进行读取。
volatile保证了修饰的共享变量在转换为汇编语言时,会加上一个以lock为前缀的指令,当CPU发现这个指令时,立即会做两件事情:将当前内核中线程工作内存中该共享变量刷新到主存、通知其他内核里缓存的该共享变量内存地址无效;这里个人记得看过一些 其实就是加了一个Lock add(备注纯属个人记忆未来会更新)
具体请看下图
-
- 不保证原子性
这是一个很大的问题,比如说10个线程同时对volatile变量进行++操作时,最后得到的值不一定是最准确的,这就是不保证原子性的例子,JVM指令:从Load到store到内存屏障,一共4步,其中最后一步jvm让这个最新的变量的值在所有线程可见,也就是最后一步让所有的CPU内核都获得了最新的值,但中间的几步(从Load到Store)是不安全的,中间如果其他的CPU修改了值将会丢失,这就是不保证原子性的原因毕竟中间出现线程不安全的情况所以无法保证。
-
- 禁止指令重排
- 原理
- 禁止指令重排
Volatile实现禁止指令重排序,从而避免多线程环境下程序出现乱序执行的现象,其实原理是使用了内存屏障,内存屏障分为两种:Load Barrier 和 Store Barrier即读屏障和写屏障。关于内存屏障这里我们下节课单独讲。
参考地址:https://www.jianshu.com/p/ef70563fe726