java 原子long_java中long和double类型操作的非原子性探究
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类型操作的非原子性探究相关推荐
- mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区
关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...
- 关于MYSQL中FLOAT和DOUBLE类型的存储
关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方式和C/C++一致准守IEEE标准他们都是浮点型的,所谓的浮点型,是小数点的位置可变,其能够表示的范围比定 ...
- java 里 泛型中 T代表什么类型
java 里 泛型中 <T>代表什么类型呀? public <T> List<T> find(String sql, Class<T> entityCl ...
- java需要最大正数_Java输出double类型中的最小正数和最大正数
这是<写给大忙人看的java核心技术>中的一道练习题. 1. 输出最大正数值 System.out.println(Double.MAX_VALUE); 直接输出包装类Double的MAX ...
- java中int转换double类型_Java 程序将int类型变量转换为double
Java 程序将int类型变量转换为double 在此程序中,我们将学习如何在Java中将整数(int)变量转换为double值. 要理解此示例,您应该了解以下Java编程主题: 示例1:使用类型转换 ...
- java double相加_解决java中两个double类型的值相加
代码: /** * 提供精确的加法运算 * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(doub ...
- qt中如何由Double类型变为QString类型以及chop()的使用
在用QT5.3写个计算器程序,需要用到把LCD中的字体变为QString类型,在网上找了一些资料不会用找了,就翻查帮助文档,终于找到了下面的提示: </pre>QString str;&l ...
- java d long_java 中long型数据的对比
在对比之前先看一个程序吧 Long a = new Long(3); Long b = new Long(3); System.out.println(a.equals(b)); Long c = n ...
- Java String和Date的转换 Date类型操作
String->Date String dateString = "2012-12-06 "; try {SimpleDateFormat sdf = new SimpleD ...
最新文章
- sudo重定向失败解决方法
- IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议
- IBM服务器win7系统忘记密码,图文详解Win7系统忘记开机密码的处理方法
- 方立勋_30天掌握JavaWeb_使用httpUrlConnection模似ie
- CNN中的卷积核及TensorFlow中卷积的各种实现
- 用openswan 2.4.7构建ipsec ×××笔记
- 每日codewars题之判断一个数是否是水仙花数
- .net reactor 学习系列(五)---.net reactor针对De4Dot脱壳工具的应对
- java 事务嵌套_Java事务以及嵌套事务
- laravel7 LogicException Please make sure the PHP Redis extension is installed and enabled
- HTML个人网站设计(源码)
- 中等分辨率卫星影像幅宽大比拼
- surface哪些可以升级win11
- 说说 Bootstrap 表格样式
- 西门子SMART200程序 PID的控制写法,突破8路,PID直接做成子程序
- 【Git】Git 的基本使用
- 小孩发烧怎么办 - 强烈建议查看转载内容的详情,看视频介绍
- Oracle数据库,基础知识
- qs.js库 使用方法
- 2021胡润百富榜出炉:数据告诉你钟睒睒如何成为中国首富