java中基本类型中,long和double的长度都是8个字节,32位(4字节)处理器对其读写操作无法一次完成,那么,JVM,long和double是原子性的吗?
创新互联成都网站建设按需定制网站,是成都网站设计公司,为广告制作提供网站建设服务,有成熟的网站定制合作流程,提供网站定制设计服务:原型图制作、网站创意设计、前端HTML5制作、后台程序开发等。成都网站推广热线:028-86922220
首先,通过一段程序对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();
- }
- }
可以看到,程序中有两条线程t1,t2;t1,t2各自不停的给long类型的静态变量field赋值为1,-1;t1,t2每次赋值后,会读取field的值,若field值既不是1又不是-1,就将field的值打印出来。
如果对long的写入和读取操作是原子性的,那么,field的值只可能是1或者-1
运行结果如下:
- 32-bit
- 出现错误结果-4294967295
- 运行正确
可以看出,当线程t1,t2同时对long进行写的时候,long出现了既不是t1写入的值,又不是t2写入的值。46 张 PPT 弄懂 JVM 调优,推荐看下。
可以推测,jvm中对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
For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.
Writes and reads of volatile long and double values are always atomic.
Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
Some implementations may find it convenient to divide a single write action on a 64-bit long or double value into two write actions on adjacent 32-bit values. For efficiency's sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to perform writes to long and double values atomically or in two parts.
Implementations of the Java Virtual Machine are encouraged to avoid splitting 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.
从规定中我们可以知道:
从程序得到的结果来看,32位的HotSpot没有把long和double的读写实现为原子操作。在读写的时候,分成两次操作,每次读写32位。因为采用了这种策略,所以64位的long和double的读与写都不是原子操作。
对于64bit的环境来说,单次操作可以操作64bit的数据,即可以以一次性读写long或double的整个64bit。因此我们可以猜测,在64位的环境下,long和double的读写有可能是原子操作。在换了64位的JVM之后,多次运行,结果都是正确的
- 64-bit
- 运行正确
- 运行正确
结果表明,在64bit的虚拟机下,long的处理是原子性的。最后,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 JVM 系列面试题和答案,非常齐全。
新闻名称:Java中long是不是原子操作?
网页路径:http://www.csdahua.cn/qtweb/news35/402735.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网