内存可见性问题,当多个线程操作共享数据时,彼此不可见.
下面的代码显示了内存不可见
package com.atguigu.juc;
import com.sun.xml.internal.bind.v2.model.annotation.RuntimeAnnotationReader;
public class TestVolatile {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
Thread thread = new Thread(td);
thread.start();
while (true) {
/*
* while 其实调用的是系统底层的代码,它的执行效率非常的高 , 搞到main 线程没有机会去底层拿到数据 所以 flag 一直是false
* 这就产生了类存可见性的问题
*/
if (td.isFlag()) {
System.out.println("================");
break;
}
}
}
}
class ThreadDemo implements Runnable {
private boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag = " + isFlag());
}
public boolean isFlag() {
return flag;
}
public void setFlag (boolean flag) {
this.flag = flag;
}
}
输出结果:
flag = true
main 线程没有读到 子线程更改后的 flage的值
造成的原因: while 其实调用的是系统底层的代码,它的执行效率非常的高 , 搞到main 线程没有机会去底层拿到数据 所以 flag 一直是false这就产生了类存可见性的问题.
解决 1 : 同步锁可以解决问题 (synchronized 会刷新缓存) , 但是效率会降低(多线程会阻塞).
synchronized (td) {
if (td.isFlag()) {
System.out.println("================");
break;
}
}
输出结果:
================
flag = true
解决2 : volatile 关键字: 当多个线程进行操作共享数据时,可以保持内存中的数据可见性.(线程都是直接操作主存中数据) 保持一致性.
private volatile boolean flag = false;