Java中的原子操作包括:

1)除long和double之外的基本类型的赋值操作

2)所有引用reference的赋值操作

3)java.concurrent.Atomic.* 包中所有类的一切操作。

但是java对long和double的赋值操作是非原子操作!!long和double占用的字节数都是8,也就是64bits。在32位操作系统上对64位的数据的读写要分两步完成,每一步取32位数据。这样对double和long的赋值操作就会有问题:如果有两个线程同时写一个变量内存,一个进程写低32位,而另一个写高32位,这样将导致获取的64位数据是失效的数据。因此需要使用volatile关键字来防止此类现象。volatile本身不保证获取和设置操作的原子性,仅仅保持修改的可见性。但是java的内存模型保证声明为volatile的long和double变量的get和set操作是原子的。(from http://www.iteye.com/topic/213794)

举个例子来说:(example is from http://stackoverflow.com/questions/17481153/long-and-double-assignments-are-not-atomic-how-does-it-matter)

public class UnatomicLong implements Runnable {

private static long test = 0;

private final long val;

public UnatomicLong(long val) {

this.val = val;

}

public void run() {

while (!Thread.interrupted()) {

test = val; //两个线程都试图将自己的私有变量val赋值给类私有静态变量test

}

}

public static void main(String[] args) {

Thread t1 = new Thread(new UnatomicLong(-1));

Thread t2 = new Thread(new UnatomicLong(0));

System.out.println(Long.toBinaryString(-1));

System.out.println(pad(Long.toBinaryString(0), 64));

t1.start();

t2.start();

long val;

while ((val = test) == -1 || val == 0) {

//如果静态成员test的值是-1或0,说明两个线程操作没有交叉

}

System.out.println(pad(Long.toBinaryString(val), 64));

System.out.println(val);

t1.interrupt();

t2.interrupt();

}

// prepend 0s to the string to make it the target length

private static String pad(String s, int targetLength) {

int n = targetLength - s.length();

for (int x = 0; x < n; x++) {

s = "0" + s;

}

return s;

}

}

运行发现程序在while循环时进入了死循环,这是因为使用的JVM是64bits。在64位JVM中double和long的赋值操作是原子操作。

在eclipse中修改jre为一个32bit的JVM地址,则会有如下运行结果:

1111111111111111111111111111111111111111111111111111111111111111

0000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000011111111111111111111111111111111

//很明显test的值被破坏了

4294967295

java 原子long_java中long和double类型操作的非原子性探究相关推荐

  1. mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区

    关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...

  2. 关于MYSQL中FLOAT和DOUBLE类型的存储

    关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方式和C/C++一致准守IEEE标准他们都是浮点型的,所谓的浮点型,是小数点的位置可变,其能够表示的范围比定 ...

  3. java 里 泛型中 T代表什么类型

    java 里 泛型中 <T>代表什么类型呀? public <T> List<T> find(String sql, Class<T> entityCl ...

  4. java需要最大正数_Java输出double类型中的最小正数和最大正数

    这是<写给大忙人看的java核心技术>中的一道练习题. 1. 输出最大正数值 System.out.println(Double.MAX_VALUE); 直接输出包装类Double的MAX ...

  5. java中int转换double类型_Java 程序将int类型变量转换为double

    Java 程序将int类型变量转换为double 在此程序中,我们将学习如何在Java中将整数(int)变量转换为double值. 要理解此示例,您应该了解以下Java编程主题: 示例1:使用类型转换 ...

  6. java double相加_解决java中两个double类型的值相加

    代码: /** * 提供精确的加法运算 * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(doub ...

  7. qt中如何由Double类型变为QString类型以及chop()的使用

    在用QT5.3写个计算器程序,需要用到把LCD中的字体变为QString类型,在网上找了一些资料不会用找了,就翻查帮助文档,终于找到了下面的提示: </pre>QString str;&l ...

  8. java d long_java 中long型数据的对比

    在对比之前先看一个程序吧 Long a = new Long(3); Long b = new Long(3); System.out.println(a.equals(b)); Long c = n ...

  9. Java String和Date的转换 Date类型操作

    String->Date String dateString = "2012-12-06 "; try {SimpleDateFormat sdf = new SimpleD ...

最新文章

  1. sudo重定向失败解决方法
  2. IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议
  3. IBM服务器win7系统忘记密码,图文详解Win7系统忘记开机密码的处理方法
  4. 方立勋_30天掌握JavaWeb_使用httpUrlConnection模似ie
  5. CNN中的卷积核及TensorFlow中卷积的各种实现
  6. 用openswan 2.4.7构建ipsec ×××笔记
  7. 每日codewars题之判断一个数是否是水仙花数
  8. .net reactor 学习系列(五)---.net reactor针对De4Dot脱壳工具的应对
  9. java 事务嵌套_Java事务以及嵌套事务
  10. laravel7 LogicException Please make sure the PHP Redis extension is installed and enabled
  11. HTML个人网站设计(源码)
  12. 中等分辨率卫星影像幅宽大比拼
  13. surface哪些可以升级win11
  14. 说说 Bootstrap 表格样式
  15. 西门子SMART200程序 PID的控制写法,突破8路,PID直接做成子程序
  16. 【Git】Git 的基本使用
  17. 小孩发烧怎么办 - 强烈建议查看转载内容的详情,看视频介绍
  18. Oracle数据库,基础知识
  19. qs.js库 使用方法
  20. 2021胡润百富榜出炉:数据告诉你钟睒睒如何成为中国首富

热门文章

  1. integer为null_走进 JDK 之 Integer
  2. 剑指offer-序列化二叉树
  3. mysql流程函数if之类
  4. 别乎略安身立命的基础本领
  5. 研发管理三部曲——贰 · 研发管理应该干什么
  6. IDL中的HRESULT值
  7. Debug学习资源汇总
  8. 华为机试HJ26:字符串排序
  9. java给一个类添加属性_给java虚拟机增加一个属性,java -D
  10. mysql新增加密字段_mysql字段加密