volatile修饰引用类型能否保证可见性似乎一直没有一个定论,有的书中说仅能保证引用本身的可见性,下面用两段代码来验证:流程基本为一个线程死循环读取某个引用类型的某个变量的值,另一个线程修改这个值,观察线程是否结束。
//volatile修饰类
public class TestVolatile implements Runnable{
class Foo {
boolean flag = true;
}
private volatile Foo foo = new Foo(); //
public void stop(){
foo.flag = false;
}
@Override
public void run() {
while (foo.flag){}
}
public static void main(String[] args) throws InterruptedException {
TestVolatile test = new TestVolatile();
Thread t = new Thread(test);
t.start();
Thread.sleep(1000);
test.stop();
}
}
//volatile修饰数组
public class TestVolatile2 implements Runnable{
private int len = 1024*1024;
volatile int[] arr = new int[len]; //
{
arr[len-1] = 1;
}
public void stop(){
arr[len-1] = 0;
}
@Override
public void run() {
while (arr[len-1] == 1){}
}
public static void main(String[] args) throws InterruptedException {
TestVolatile2 test = new TestVolatile2();
Thread t = new Thread(test);
t.start();
Thread.sleep(1000);
test.stop();
}
}
上面两段代码在有volatile字段的时候可观察到程序停止运行,没有volatile字段的时候会一直运行下去。