Java中线程间可见性错误分析
题目描述
在验证volatile关键字时,发现了这个场景:代码里注释行执行和不执行,最后的结果不一样。
当注释掉打印的信息时,业务逻辑会死循环执行,可以理解
当释放掉注释之后,业务逻辑 就能读取到 子线程修改的值
题目来源及自己的思路
相关代码
public class VolatileTest {public static void main(String[] args) {
VolatileThread thread = new VolatileThread();
thread.start();
while (true) {
// System.out.println("thread.isFlag():" + thread.isFlag());
if (thread.isFlag()) {
System.out.println("----------------------");
break;
}
}
}
public static class VolatileThread extends Thread {
public boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag= " + flag);
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
}
你期待的结果是什么?实际看到的错误信息又是什么?
注释 sout的结果
执行 sout的结果
回答
主要原因是执行System.out.println
和其他语句相比而言,
非常慢,涉及很多的内部操作, 造成 CPU 缓存失效。所以起的作用相当于让主线程终于有机会看到 flag 发生了变化。
可以加上 count 比较一下(我机器上有输出时循环执行70399次,没有输出时循环执行了801053907次)。
最终多线程共享变量还是要用volatile
关键字来处理可见性的问题:
public volatile boolean flag = false;
以上是 Java中线程间可见性错误分析 的全部内容, 来源链接: utcz.com/a/27413.html