一问题:多线程模式下会产生数据读写的不一致问题:如图
解决方案:
- 总线加锁(粒度太大)
- MESI()
- 读操作:不做任何事情,把Cache中的数据读到寄存器
- 写操作:发出信号通知其他的CPU讲改变量的Cache line置为无效,其他的CPU要访问这个变量的时候,只能从内存中获取。
Cache line CPU的cache中会增加很多的Cache line
二:Volatile关键字的语义
volatile作用:让其他线程能够马上感知到某一线程多某个变量的修改
- 保证可见性
对共享变量的修改,其他的线程马上能感知到
不能保证原子性 读、写、(i++)
- 保证有序性
重排序(编译阶段、指令优化阶段)
输入程序的代码顺序并不是实际执行的顺序
重排序后对单线程没有影响,对多线程有影响
Volatile
Happens-before
volatile规则:
对于volatile修饰的变量:
- volatile之前的代码不能调整到他的后面
- volatile之后的代码不能调整到他的前面(as if seria)
- 霸道(位置不变化)
- volatile的原理和实现机制(锁、轻量级)
-
HSDIS --反编译---汇编
Java --class---JVM---》ASM文件
Volatile int a ;
Lock :a
三:Volatile的使用场景
- 状态标志(开关模式)
- 双重检查锁定(double-checked-locking)饿汉模式
- 需要利用顺序性
四:volatile与synchronized的区别
- 使用上的区别
Volatile只能修饰变量,synchronized只能修饰方法和语句块
- 对原子性的保证
synchronized可以保证原子性,Volatile不能保证原子性
- 对可见性的保证
都可以保证可见性,但实现原理不同
Volatile对变量加了lock,synchronized使用monitorEnter和monitorexit monitor JVM
- 对有序性的保证
Volatile能保证有序,synchronized可以保证有序性,但是代价(重量级)并发退化到串行
- 其他
synchronized引起阻塞
Volatile不会引起阻塞