可见性问题的引出
一个线程要改堆中的变量,有8个原子操作,有时候会出现一些问题。见如下示例:
boolean flag=true;
public static void main(){
Thread t1 = new Thread (new Runnable(){
@Override
public void run(){// 线程结束 run方法执行完成
System.out.println ("线程 1 开始");
while(flag){
//这里在flag被修改前是个死循环,使得线程不能结束
}
System.out.println ("因flag被修改,线程 1 结束");
}
});
Thread t2 = new Thread (new Runnable(){
@Override
public void run(){// 线程结束 run方法执行完成
System.out.println ("线程 2 开始");
flag=false;
System.out.println ("修改了flag,线程 2 结束");
}
});
t1.start();// 启动t1
try {
Thread.sleep (2000);// 线程睡眠2秒
} catch (InterruptedException e) {
e.printStackTrace ();
}
t2.start();// 启动t2
}
按理来说,输出应该是:
线程一开始
线程二开始
修改了flag,线程 2 结束
因flag被修改,线程 1 结束
可是,实际上线程一并没有结束。因为线程二虽然改了flag,可是线程一不知道!
解决办法
volatile关键字
用volatile修饰flag,使得flag一旦被修改,其他线程就能知道。
volatile是不能保证原子操作的,也就是不能保证线程安全。先要线程安全,还是要靠锁。