long和double的非原子性协定(Nonatomic Treatment of double and long Variable)
Java内存模型要求lock、unlock、read、load、assign、use、store、write这8个操作都具有原子性,但是对于64位的数据类型(double、long)定义了相对宽松的规定:允许虚拟机将没有被volatile修饰的64位数据的读写操作划分为两次的32位操作来进行,即允许虚拟机可以不保证64位数据类型的load、store、read和write操作的原子性。
非原子性协定可能导致的问题
如果有多个线程共享一个未申明为volatile的long或double类型的变量,并且同时对其进行读取和修改操作,就有可能会有线程读取到"半个变量"的数值或者是一半正确一半错误的失效数据。
在实际应用中的解决
因为上述可能造成的问题,势必在对long和double类型变量操作时要加上volatile关键字,实际上如下:
1、64位的java虚拟机不存在这个问题,可以操作64位的数据
2、目前商用JVM基本上都会将64位数据的操作作为原子操作实现
所以我们编写代码时一般不需要将long和double变量专门申明为volatile