Volatile
先了解JMM【Java内存模型】
如上图,如果A线程修改s的值,线程B读取s的值,可能会出现问题
解决
使用volatile关键字
volatile的作用
可见性
volatile修饰的变量对所有线程的可见性
可见性:当一个变量修改了变量的值后,立刻同步到主存中
为什么volatile关键字可以有这样的特性?这得益于java语⾔的先行发生的原则
先⾏发⽣原则是两个事件的结果之间的关系,如果⼀个事件发⽣在另⼀个事件之前,结果必须反映,即使这些事件实际上是乱序执⾏的(通常是优化程序流程)
阻止指令重排序
正常顺序
- 堆中申请空间
- 创建对象
- 地址赋值给栈
重排序后的顺序
由于2的时间较长,会优化成1、3、2
可能出现空指针
解决指令重排序
内存屏障:一种CPU指令
分为4种类型:
- 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屏障的开销是四种屏障中最⼤的