Java多线程_0x4_
多线程篇四——volatile关键字
如笔者理解有误,欢迎交流指正⭐
首先我们要明晰的一点是计算机运行程序或代码时经常要访问数据,这些依赖的数据往往存储在内存中.
CPU使用变量的时候需要先从内存中读取出来放到CPU的寄存器中|由此我们可得读内存比读硬盘快,读寄存器比读内存快,但是CPU一旦涉及读/写内存速率很低.此时我们聪明得编译器就会帮忙了(虽然有时候会帮倒忙) 编译器可能会对代码做出优化,减少读内存的次数。提高整体的效率.
volatile能保证内存可见性
上代码
1 | import java.util.Scanner; |
运行发现
当我输入6的时候,并没有输出”game over!” 按理来说修改flg的值不为0的时候会输出”game over!”为什么会出现异常呢?
这就是我们的内存可见性问题.
读取flg的值这个过程分为两步走.
1 | 1.load读取内存中的flg值到寄存器中. |
乍一看这么处理不也没什么问题。但是,while循环此时飞速运转短时间内会进行大量重复的操作,这样就出现了最开头介绍的小聪明编译器.big 胆就水灵灵优化上了😀
只在第一次循环的时候读内存后续直接从寄存器中取出数据
由于修改flg是t2线程非t1线程本身,编译器没有正确的判定(提高效率不保证逻辑不变哈)以为flg未被修改就直接启动优化了,t1感受不到修改过后的flg的内存变化
如何避免小聪明不要帮倒忙?这就需要聪明的你使用volatile关键字提醒编译器.【强制爱读取内存】
被volatile修饰的变量的的读写操作相关指令,是不可以重排序的.
1 | import java.util.Scanner; |
当然解决内存可见性问题的方法出了从根部抹杀(volatile关键字)还可以规避问题(sleep延缓开销速率 优化也没必要进行了)
volatile不保证原子性
volatile 和 synchronized 有着本质的区别. synchronized 能够保证原子性, volatile 保证的是内存可见性.
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 幻境!
评论