说明
- 多线程程序中,内存可见性问题,示例:
如下代码会出现死循环问题:
class Thread1 implements Runnable {
boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
flag = true;
}
}
public class Volatile {
public static void main(String[] args) {
Thread1 t1 = new Thread1();
new Thread(t1).start();
System.out.println(t1.flag);
while (true) {
if (t1.flag) {
System.out.println("true--------");
break;
}
}
}
}
出现死循环的原因是,每个线程都会开辟一块缓存内存用于操作共享数据,在堆共享数据操作完成后再返还给主存,在上面的程序中,t1线程执行中睡了1秒,这时主线程获取了执行权开始循环,并判断flag为假,而t1睡眠结束后修改了flag的值后,主线程获取的flag值是缓存中的flag值,所以一直循环,无法结束。
解决方法:volatile关键字修饰线程共享数据volatile boolean flag = false;
。被volatile修饰的变量,被操作时不会在缓存中,而是在主存中,这样就保证了线程间操作的可见性。
- volatile关键字的注意事项:
(1)不具备synchronize的互斥性
(2)不能保证变量的“原子性”
(3)被修饰的变量不会被jvm优化重排序