一直想用代码验证一下使用volatile和不适用volatile对变量可见性的影响,google找到的几个代码示例似乎都不太严密,于是写了一个,不知道是否也不严密,大家帮忙看看,如果有好的验证代码也请提供一下。
先给一个不使用volatile关键字,导致变量不可见的例子
public class VolatileTest {
private int i = 0;
private int j = 0;
public long exceptionCount = 0;
//线程1调用这个方法
public void f1() {
for(int k = 0; k < Integer.MAX_VALUE; k++) {
i = k;
j = i;
}
}
//线程2调用这个方法
public void f2() {
while (true) {
//如果线程1对i,j的修改都是可见的,就不会出现j>i的情况了,一旦出现这种情况就能说明线程1对i,j的修改不可见
if(j > i) {
exceptionCount++;
}
}
}
public static void main(String[] args) {
final VolatileTest volatileTest = new VolatileTest();
//线程1
new Thread(new Runnable() {
@Override
public void run() {
volatileTest.f1();
}
}).start();
//线程2
new Thread(new Runnable() {
@Override
public void run() {
volatileTest.f2();
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("exceptionCount:" + volatileTest.exceptionCount);
}
}
输出结果为:
exceptionCount:6542138604
可以看到exceptionCount大于0,说明线程1对变量i,j的修改对线程2不可见。
如果给i,j加上volatile关键字,则线程1对变量i,j的修改对线程2可见,下面给出代码:
public class VolatileTest {
private volatile int i = 0;
private volatile int j = 0;
public long exceptionCount = 0;
public void f1() {
for(int k = 0; k < Integer.MAX_VALUE; k++) {
i = k;
j = i;
}
}
public void f2() {
while (true) {
if(j > i) {
exceptionCount++;
}
}
}
public static void main(String[] args) {
final VolatileTest volatileTest = new VolatileTest();
new Thread(new Runnable() {
@Override
public void run() {
volatileTest.f1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
volatileTest.f2();
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("exceptionCount:" + volatileTest.exceptionCount);
}
}
输出结果为:
exceptionCount:0
从结果可以看出,线程1对变量i,j的修改对线程2可见。