public static void main(String[] args) {
MyThread01 t = new MyThread01();
t.start();
while (true){
if (t.isFlag()){
System.out.println("entry");
}
} //flag先true后false导致不可见性,而且加sout和sleep会恢复
//先false后true不会
}
}
class MyThread01 extends Thread {
public boolean flag = false;
public void run() {
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println(flag);
}
public boolean isFlag() {
return flag;
}
}
//这个不会发生可见性问题
这是因为在Java中,多线程之间的变量共享需要遵循一些规则来确保可见性。当一个线程修改变量时,其它线程可能并不能立即看到这个修改。在第一种情况中,主线程在子线程执行完之前就读取了变量的值,而子线程修改了变量之后主线程并不能立即看到这个修改,因此导致了不可见性问题。在第二种情况中,子线程在主线程读取变量之前就已经修改了变量,因此主线程能够看到这个修改。
在第一种情况中,加入sout和sleep的作用是在修改变量之后让主线程有时间读取到修改后的值,因此可见性问题得到了解决。
具体来说,解决方法有:
使用volatile关键字修饰变量,这个关键字可以禁止指令重排和缓存,保证可见性.
使用synchronized关键字修饰变量或方法,这个关键字可以禁止多线程并发访问,保证可见性.
使用Lock锁,这个锁可以禁止多线程并发访问,保证可见性.
使用Atomic类,这个类提供了CAS算法,保证可见性.