long和double类型变量的非原子性

“深入java虚拟机”中提到,int等不大于32位的基本类型的操作都是原子操作,但是某些jvm对long和double类型的操作并不是原子操作,这样就会造成错误数据的出现。 

错误数据出现的原因是: 
对于long和double变量,把它们作为2个原子性的32位值来对待,而不是一个原子性的64位值, 
这样将一个long型的值保存到内存的时候,可能是2次32位的写操作, 
2个竞争线程想写不同的值到内存的时候,可能导致内存中的值是不正确的结果。 

1、写入高位32位值(线程2) 
2、写入高位32位值(线程1) 
3、写入低位32位值(线程1)   
4、写入低位32位值(线程2) 

这样内存中的值变成线程1的高32位值和线程2的低32位值的组合,是个错误的值。 
书中还提到,上面出现问题的long和double变量是没有声明为volatile的变量。

以下是jvm spec中的原文引用:

If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write operations it is treated as if it were two variables of 32 bits each; wherever the rules require one of these operations, two such operations are performed,one for each 32-bit half. The manner in which the 64 bits of a double or long variable are encoded into two 32-bit quantities and the order of the operations on the halves of the variables are not defined by The Java  LanguageSpecification. 
 
This matters only because a read or write of a double or long variable may behandled by an actual main memory as two 32-bit read or write operations that may be separated in time, with other operations coming between them.Consequently, if two threads concurrently assign distinct values to the same shared non-volatile double or long variable, a subsequent use of that variablemay obtain a value that is not equal to either of the assigned values, but rather some implementation-dependent mixture of the two values. 

An implementation is free to implement load, store, read, and write operationsfor double and long values as atomic 64-bit operations; in fact, this isstrongly encouraged. The model divides them into 32-bit halves for the sake ofcurrently popular microprocessors that fail to provide efficient atomic memorytransactions on 64-bit quantities. It would have been simpler for the Javavirtual machine to define all memory transactions on single variables asatomic; this more complex definition is a pragmatic concession to currenthardware practice. In the future this concession may be eliminated. Meanwhile,programmers are cautioned to explicitly synchronize access to shared double andlong variables. 

   volatile本身不保证获取和设置操作的原子性,仅仅保持修改的可见性。但是java内存模型保证声明为volatile的long和double变量的get和set操作是原子的。

    jvm spec引用中的最后一段说到,jvm可以很轻易的将变量操作变成原子性的,但是却受到了当前硬件的约束,因为流行的微处理器还是32bit居多,因此64bit的变量需要拆分成两次,但如果是64bit处理器就能满足64bit变量的原子性操作了。 看来,随着硬件的不断改进,这个问题以后将不会是问题了吧。

这么说的话, 64bit处理器加64位操作系统,再加上64bit的jvm是否就可满足long,double的原子性操作?

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值