java中long和double类型操作的非原子性探究
来源:互联网 发布:阿里云邮企业版下载 编辑:程序博客网 时间:2024/04/30 05:31
Java中的原子操作包括:
private static long test = 0;
private final long val;
public UnatomicLong(long val) { this.val = val; }
@Override 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; }
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 {
}
运行发现程序在while循环时进入了死循环,这是因为使用的JVM是64bits。在64位JVM中double和long的赋值操作是原子操作。
在eclipse中修改jre为一个32bit的JVM地址,则会有如下运行结果:
1111111111111111111111111111111111111111111111111111111111111111
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000011111111111111111111111111111111
//很明显test的值被破坏了
4294967295
0 0
- java中long和double类型操作的非原子性探究
- java中long和double类型操作的非原子性探究
- long和double类型变量的非原子性
- 非原子的double和long
- Java的long、double类型的原子性读取问题
- 证明32位java对long和double的写操作不是原子性的
- java volatile double、long的原子性
- volatile能保证long&double类型变量操作的原子性
- java int short long float double 类型描述以及原子性说明
- Long与double操作并不是原子的
- java中Long类型和long类型的大小比较
- Java中对非原子的64位操作
- Java中Double和Long互相转换
- Java中Double和Long互相转换
- Java中Double和Long互相转换
- 32位JVM对long类型的赋值不是原子性操作
- java中String、Long、Double等类型转换问题
- java中byte、short、int、long、float、double类型的取值范围
- 黑马程序员——反射
- git使用时遭遇the authenticity of host can't be established
- Android之异步线程原理
- MATLAB中去掉字符串中的空格,num2str引发的问题
- 大数据平台搭建之nexus私服
- java中long和double类型操作的非原子性探究
- QT5-TableWidget字符串显示
- 分享:“延迟加载与预加载”使用体会
- javascript 语法基础 想学习js的朋友可以看看
- Docker使用Link在容器之间建立连接
- webview 创建页面self.append(sub)与sub.show()区别
- fastreport问题集合
- volatile 和 atomic 原子性的区别和联系
- More than one order matters