Java 中 long 是不是原子操作?
Posted Java技术栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 中 long 是不是原子操作?相关的知识,希望对你有一定的参考价值。
点击关注公众号,Java干货及时送达
作者:LouisWong
来源:https://my.oschina.net/u/1753415/blog/724242
Java中long和double的原子性
java中基本类型中,long和double的长度都是8个字节,32位(4字节)处理器对其读写操作无法一次完成,那么,JVM,long和double是原子性的吗?
JVM中对long的操作是不是原子操作?
首先,通过一段程序对long的原子性进行判断。测试程序如下:
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 = value;
}
public LongAtomTest(long value) {
this.setValue(value);
}
@Override
public void run() {
int i = 0;
while (i < 100000) {
LongAtomTest.field = this.getValue();
i++;
long temp = LongAtomTest.field;
if (temp != 1L && temp != -1L) {
System.out.println("出现错误结果" + temp);
System.exit(0);
}
}
System.out.println("运行正确");
}
public static void main(String[] args) throws InterruptedException {
// 获取并打印当前JVM是32位还是64位的
String arch = System.getProperty("sun.arch.data.model");
System.out.println(arch+"-bit");
LongAtomTest t1 = new LongAtomTest(1);
LongAtomTest t2 = new LongAtomTest(-1);
Thread T1 = new Thread(t1);
Thread T2 = new Thread(t2);
T1.start();
T2.start();
T1.join();
T2.join();
}
}
如果对long的写入和读取操作是原子性的,那么,field的值只可能是1或者-1
运行结果如下:
32-bit
出现错误结果-4294967295
运行正确
可以看出,当线程t1,t2同时对long进行写的时候,long出现了既不是t1写入的值,又不是t2写入的值。46 张 PPT 弄懂 JVM 调优,推荐看下。
可以推测,jvm中对long的操作并非原子操作。
为什么对long的操作不是原子的?
JVM内存模型中定义了8中原子操作:
其中,与赋值,取值相关的包括 read,load,use,assign,store,write
按照这个规定,long的读写都是原子操作,与我们的实践结果相反,为什会导致这种问题呢?
对于32位操作系统来说,单次次操作能处理的最长长度为32bit,而long类型8字节64bit,所以对long的读写都要两条指令才能完成(即每次读写64bit中的32bit)。
如果JVM要保证long和double读写的原子性,势必要做额外的处理。那么,JVM有对这一情况进行额外处理吗?另外,JVM 系列面试题和答案全部整理好了,微信搜索Java技术栈,在后台发送:面试,可以在线阅读。
针对这一问题可以参考Java语言规范文档:jls-17 Non-Atomic Treatment of double and long
Writes and reads of volatile long and double values are always atomic.
从规定中我们可以知道:
从程序得到的结果来看,32位的HotSpot没有把long和double的读写实现为原子操作。在读写的时候,分成两次操作,每次读写32位。因为采用了这种策略,所以64位的long和double的读与写都不是原子操作。
在硬件,操作系统,JVM都是64位的情况下呢?
对于64bit的环境来说,单次操作可以操作64bit的数据,即可以以一次性读写long或double的整个64bit。因此我们可以猜测,在64位的环境下,long和double的读写有可能是原子操作。在换了64位的JVM之后,多次运行,结果都是正确的
64-bit
运行正确
运行正确
结果表明,在64bit的虚拟机下,long的处理是原子性的。最后,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 JVM 系列面试题和答案,非常齐全。
关注Java技术栈看更多干货
获取 Spring Boot 实战笔记!
以上是关于Java 中 long 是不是原子操作?的主要内容,如果未能解决你的问题,请参考以下文章