volatile 关键字
在修饰的变量,在系统汇编的代码里会生成lock前缀,表示指令在多核CPU情况下,在当前处理器将缓存数据写回到系统主内存时,会引起其他CPU缓存了该内存地址的数据无效。
作用:保证线程的可见性,即一个线程对变量的更改对其他线程是可知的。
volatile+原子操作保证线程安全:线程在工作内存的赋值指令assign,传输到仓库store,最后write写入主内存,这三步操作是一个整理,中间不会中断,就好像直接操作主存一样。使用volatile后,线程对变量原子操作值被修改了,会根据缓存一致性协议通知其他线程的缓存副本过期。
volatile 线程不安全例子
*缓存一致协议(MESI协议),缓存数据cache状态:
- M(Modified) :这行数据有效,缓存数据修改了与内存不一致,数据只存在于本Cache中。
- E(Exclusive):这行数据有效,缓存数据和内存中的数据一致,数据只存在于本Cache中。
- S(Shaed) : 这行数据有效,缓存数据和内存中的数据一致,数据存在于很多Cache中。
- I(Invalid) : 缓存数据无效。
2个线程进行i++操作,正确结果应该i = 3。
按照原子性操作, 3、4是线程2的原子操作, 5、6、7是线程1的原子操作。但注意第5步,工作内存的缓存数据状态为I,即缓存数据无效。
这就说明,volatile修饰的变量在多线程中是线程不安全的。