Volatile关键字可以保证多线程的可见性,无法保证原子性。
public class VolatileTest1 {
private static final int THREADS_COUNT = 20;
private static volatile int race = 0;
private static void increacse(){
race ++ ;
}
public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[THREADS_COUNT];
for (int i = 0; i <THREADS_COUNT ; i++) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10000 ; j++) {
increacse();
}
}
});
threads[i].start();
}
// 等待所有线程运行完毕
for (Thread t: threads ) {
t.join();
}
System.out.println(race);
}
}
运行结果一:
运行结果二:
显然结果无法保证一直正确;
结果不正确原因分析:假设目前只有两个线程(A和B)操作,两者都走到了increacse()这一步,也就是use,线程A先于B完成assign>store>write,此时主内存的值race = 1,因为总线嗅探机制的存在,此时B线程工作内存上的race失效,B线程重新执行read操作,读到正确的race值,然后进行下一次increacse(),也就是use,得到值2写入内存,实际这个过程中,总过执行了三次increacse(),值本应该是3,而不是2,这就是主程序结果为啥有时候不等于200000的原因。
流程如下: