微网站建设第一步是进行什么的设置,安徽茶叶网站建设,网站开发技术可行性,宣传推广策略一.内存可见性问题
什么是内存可见性问题
计算机运行的程序/代码#xff0c;往往需要访问数据。这些数据往往存在于内存中。
cup使用此变量时#xff0c;就会把内存中的数据先读出来#xff0c;加载到cpu寄存器中#xff0c;再去参与运算。
但是#xff0c;关键是cpu读…一.内存可见性问题
什么是内存可见性问题
计算机运行的程序/代码往往需要访问数据。这些数据往往存在于内存中。
cup使用此变量时就会把内存中的数据先读出来加载到cpu寄存器中再去参与运算。
但是关键是cpu读取内存的速度非常慢。这是相对的读内存比读取硬盘快成千上万倍而读取寄存器又比读取内存快了成千上万倍。而这里cpu计算时就是涉及到读取内存和读取寄存器的操作。
读取寄存器非常快一旦涉及到读内存cpu就慢下来了。为例提高效率操作系统就可能在代码逻辑不变的情况下对代码进行优化把本来读取内存的操作优化成读取寄存器的操作减少了读取内存的次数也就提高了效率。但是此时如果有另一个线程对该数进行了修改并放到内存中前一个线程就感知不到变化就会出现问题。这就出现了内存可见性问题也是线程安全问题的成因之一明明内存已经修改了值它却视而不见
例如下面的情况 明明修改了isQuit的值但线程1还在循环说明while中读取到的值还是0说明没有看到内存的修改这就是内存可见性问题是由于多线程引起的。我们来解释一下
while(isQuit0)这个判断分为俩步第一步load就是cpu读取内存将内存中isQuit的值记录到寄存器中第二步读取寄存器判断isQuit的值是否为0cmp。
由于只是一个循环短时间内就会进行大量循环也就是会进行大量loadcmp操作。但是此时JVM发现load一次的时间内就可以cmp成千上万次而且发现前几次时每次load和cmp的结果都是一样的并且load有费时所以编译器就做了大胆决定不再进行load内存而是直接从寄存器中取出isQuit。
编译器的优化初心是好的想要提高工作效率但没想到其他线程动了手脚而编译器却察觉不到所以就做出了错误决定。
其实从上述分析中我们可以大胆猜测要是循环慢一点就可能不会进行优化了如下 虽然只休眠了50毫秒但却正常了所以编译器到底什么时候触发优化机制我们无法确定。
关于内存可见性还涉及到一个JMMJava Memory ModelJava内存模型这个概念。它时说到了主内存和工作内存主内存就是我们常说的内存而寄存器缓存等统称为工作内存。
如何解决内存可见性问题
上述问题如何解决我们怎么告诉编译器不要进行优化
这就引出了volatile关键字
二.volatile关键字
volatile关键字修饰的变量能够保证内存可见性
它是如何保证被修饰的变量时内存可见性的呢分两方面一方面代码在写入或修改ivolatile修饰的变量时会先改写工作内存中的变量的值然后会将改后的值从工作内存中刷新到主内存中另一方面在读取该变量时会先将变量从主内存加载到寄存器中再从寄存器中读取。
也就是说加上volatile后会让系统强制读写内存而不是直接读写寄存器虽然速度慢了但时却保证了准确性。 volatile不能保证原子性
他只能让读取内存操作不被优化成读寄存器而不能将代码捆绑到一起。保证原子性的操作还得是用synchronized