做网站外国的,手机wap网页设计,深圳龙华建设工程交易中心网站,vs做网站添加背景保证了不同线程对这个变量进行操作时的可见性#xff0c;即一个线程修改了某个变量的值#xff0c;这新值对其他线程来说是立即可见的,volatile关键字会强制将修改的值立即写入主存。
1.volatile的可见性
一个典型的例子#xff1a;永不停止的循环。 public class Forever… 保证了不同线程对这个变量进行操作时的可见性即一个线程修改了某个变量的值这新值对其他线程来说是立即可见的,volatile关键字会强制将修改的值立即写入主存。
1.volatile的可见性
一个典型的例子永不停止的循环。 public class ForeverLoop {static boolean stop false;public static void main(String[] args) {new Thread(() - {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}stop true;System.out.println(modify stop to true...);}).start();foo();}static void foo() {int i 0;while (!stop) {i;}System.out.println(stopped... c: i);}}
当执行上述代码的时候发现foo()方法中的循环是结束不了的也就说读取不到共享变量的值结束循环。
主要是因为在JVM虚拟机中有一个JIT即时编辑器给代码做了优化。
上述代码
while (!stop) {
i;
}
在很短的时间内这个代码执行的次数太多了当达到了一个阈值JIT就会 优化此代码如下
while (true) {
i;
}
当把代码优化成这样子以后及时 stop 变量改变为了 false 也依然停止不了循环。
解决方案
在修饰 stop 变量的时候加上 volatile ,表示当前代码禁用了即时编辑器问题就可以解决代码如下
static volatile boolean stop false; 2.指令重排序问题 出现该问题的原因
简单说就是JVM为了对代码进行优化提高性能会在不影响结果的情况下把代码执行顺序改变但多线程就可能会出现结果不对的问题。
解决方案添加volatile关键字
volatile原理就是加了一些屏障使屏障后的代码一定不会比屏障前的代码先执行从而实现有序性。
给变量y添加关键字的屏障添加的示意图 写操作加的屏障是阻止上方其它写操作越过屏障排到volatile变量写之下阻止了 x 1 走到 y 1 之后
读操作加的屏障是阻止下方其它读操作越过屏障排到volatile变量读之上同上x 的读走到 y 的读之前 补充为什么不能给x变量添加关键字
给变量x添加关键字的屏障添加的示意图 这样显然是不行的主要是因为下面两个原则 1.写操作加的屏障是阻止上方其它写操作越过屏障排到volatile变量写之下这个屏障只能阻止 x 1y 1这两行代码上方的指令越过该屏障它不能阻止 y 1往上走到 x 1之前 2.读操作加的屏障是阻止下方其它读操作越过屏障排到volatile变量读之上
所以现在我们就可以总结一个volatile使用的小妙招 写变量让volatile修饰的变量的在代码最后位置 读变量让volatile修饰的变量的在代码最开始位置