Java普通变量(未用volatile的修饰)的读和写是否是原子性的?
再读《java并发编程艺术》这本书的时候学到了volatile,作者在书中强调了,volatile可以保证读和写具有原子性。让我心生疑惑难道普通的变量读和写就不具有原子性了吗?我记得好多人都曾说过java普通变量的赋值和读取操作是原子性的。
然后这一堆概念在我脑子里变成了浆糊,它们似乎冲突着矛盾着,但又各自有各自的道理。
我对原子性真的感到十分疑惑。
我试着这样分析一下:
读取一个变量需要两部操作从主内存read出来,然后再load到工作内存,如果这两个指令中间重排序了其他的指令,那这样看来,读取一个变量真的不是原子操作。
给一个变量赋值,也是有多个指令组成,如果中间加入了其他的操作那也谈不上原子性了。
这样分析的话普通变量赋值和读取严格意义上谈不上原子操作,但是这样分析感觉别人说的赋值和读取是不可分割的又十分的冲突。
到底什么才是原子操作,就好比一个线程修改了一个普通变量,但是它没有及时写会主内存,它还是原子操作吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
引用是, int等基本類型是
只有long和double不保證是
这本书我很早以前看过 我记得没错的话 书上也应该说了是32位JVM读写long double这种64位数据的情况会有问题吧...
不是,原子操作完成后的影响一定是可见的
volatile 关键字解决的不是原子性问题, 而可见性问题.
多核多 CPU 环境下, 每个线程可能因 CPU 高速缓存各自分离的原因, 一个线程看不到另一个线程修改的结果, 因为缓存还没有刷新到主内存的原因. volatile 关键字确保每次在做修改时都直接写入主内存(或同步高速缓存). 从而保障各个线程都能看到修改结果.
可以参考这里:The Java® Language Specification Java SE 8 Edition
在虚拟机规范中并没有规定对非 volatile 的 double 和 long 的读写是原子的,但是虚拟机的具体实现也可以是原子的,对于 volatile 修饰的,读写必须为原子的。
经测试,在 32 位的 intel 机器上,不是原子的,在 64 位的 intel 机器上是原子的