long 和 double 的原子性问题

       在java中,long和double都8个字节共64位(一个字节=8bit),那么如果是一个32位的系统,读写long或double的变量时,会不会涉及到原子性问题?答案是确定的,因为32位的系统要读完一个64位的变量,需要分两步执行,每次读取32位,这样就对double和long变量的赋值就会出现问题:
       如果有两个线程同时写一个变量内存,一个进程写低32位,而另一个写高32位,这样将导致获取的64位数据是失效的数据。

public class LongTest implements Runnable{
    private static long aLong = 0;
    private volatile long value;
    
    public LongTest(long value) {
        this.setValue(value);
    }

    @Override
    public void run() {
        int i = 0;
        while (i < 100000) {
            LongTest.aLong = this.getValue();
            i++;
            long temp = LongTest.aLong;
            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 sysNum = System.getProperty("sun.arch.data.model");
        System.out.println("系统的位数:"+sysNum);
        LongTest t1 = new LongTest(1);
        LongTest t2 = new LongTest(-1);
        Thread T1 = new Thread(t1);
        Thread T2 = new Thread(t2);
        T1.start();
        T2.start();
        T1.join();
        T2.join();
    }
    public long getValue() {
        return value;
    }
    public void setValue(long value) {
        this.value = value;
    }
}

上面的代码在32位环境和64位环境执行的结果是不一样的:
32位环境:出现错误结果
原因:32位环境无法一次读取long类型数据,多线程环境下对aLong变量的读写是不完整的,导致temp变量既不等于1也不等于01
64位环境:运行正确

解决方法:因此需要使用volatile关键字来防止此类现象

  • 对于64位的long和double,如果没有被volatile修饰,那么对其操作可以不是原子的。在操作的时候,可以分成两步,每次对32位操作。
  • 如果使用volatile修饰long和double,那么其读写都是原子操作

如果是在64位的系统中,那么对64位的long和double的读写都是原子操作的。即可以以一次性读写long或double的整个64bit。

参考:https://mp.weixin.qq.com/s/Zfv9SjQeAtjnT4xVwTsa2g
https://my.oschina.net/u/2401092/blog/1920239

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java虚拟机规范定义的许多规则中的一条:所有对基本类型的操作除了某些对long类型和double类型的操作之外,...
    luoyoub阅读 5,469评论 0 1
  • 目录: 1. 指令重排 2. 顺序一致性 3. volatile 4. final 1.指令重排 要了解指令重排,...
    西部小笼包阅读 4,134评论 0 1
  • 除了充分利用计算机处理器的能力外,一个服务端同时对多个客户端提供服务则是另一个更具体的并发应用场景。衡量一个服务性...
    胡二囧阅读 5,176评论 0 12
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 13,851评论 6 13
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,430评论 11 349