long和double作为java中的基本数据类型,当我们读取一个基本数据类型的时候,自然而然想的就是线程安全的,但是其实不然,jvm的原子操作有以下几种:
lock:将一个变量标识为被一个线程独占状态
unclock:将一个变量从独占状态释放出来,释放后的变量才可以被其他线程锁定
read:将一个变量的值从主内存传输到工作内存中,以便随后的load操作
load:把read操作从主内存中得到的变量值放入工作内存的变量的副本中
use:把工作内存中的一个变量的值传给执行引擎,每当虚拟机遇到一个使用到变量的指令时都会使用该指令
assign:把一个从执行引擎接收到的值赋给工作内存中的变量,每当虚拟机遇到一个给变量赋值的指令时,都要使用该操作
store:把工作内存中的一个变量的值传递给主内存,以便随后的write操作
write:把store操作从工作内存中得到的变量的值写到主内存中的变量
但是当我们load一个long变量时,32位的操作系统单次操作的最大数据为32位,那么jvm读取一个64位的long类型时,会分为两次读取,如果有两个线程都在读,那么可能会导致两个线程读取long的高位和地位错位,导致读取错误
下面有个测试程序可以验证,32位的操作系统会出现问题:
public class LongAtomTest implements Runnable {
private static long field = 0;
private volatile long value;
public long getValue() {
return value;
}
public void setValue(long value) {
this.value &