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

回到顶部