Java普通变量(未用volatile的修饰)的读和写是否是原子性的?

发布于 2022-09-11 18:47:20 字数 449 浏览 42 评论 0

再读《java并发编程艺术》这本书的时候学到了volatile,作者在书中强调了,volatile可以保证读和写具有原子性。让我心生疑惑难道普通的变量读和写就不具有原子性了吗?我记得好多人都曾说过java普通变量的赋值和读取操作是原子性的。
然后这一堆概念在我脑子里变成了浆糊,它们似乎冲突着矛盾着,但又各自有各自的道理。
我对原子性真的感到十分疑惑。

我试着这样分析一下:
读取一个变量需要两部操作从主内存read出来,然后再load到工作内存,如果这两个指令中间重排序了其他的指令,那这样看来,读取一个变量真的不是原子操作。
给一个变量赋值,也是有多个指令组成,如果中间加入了其他的操作那也谈不上原子性了。
这样分析的话普通变量赋值和读取严格意义上谈不上原子操作,但是这样分析感觉别人说的赋值和读取是不可分割的又十分的冲突。
到底什么才是原子操作,就好比一个线程修改了一个普通变量,但是它没有及时写会主内存,它还是原子操作吗?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

却一份温柔 2022-09-18 18:47:20

引用是, int等基本類型是

只有long和double不保證是

李白 2022-09-18 18:47:20

再读《java并发编程艺术》这本书的时候学到了volatile,作者在书中强调了,volatile可以保证读和写具有原子性

这本书我很早以前看过 我记得没错的话 书上也应该说了是32位JVM读写long double这种64位数据的情况会有问题吧...

到底什么才是原子操作,就好比一个线程修改了一个普通变量,但是它没有及时写会主内存,它还是原子操作吗?

不是,原子操作完成后的影响一定是可见的

梦过后 2022-09-18 18:47:20

volatile 关键字解决的不是原子性问题, 而可见性问题.
多核多 CPU 环境下, 每个线程可能因 CPU 高速缓存各自分离的原因, 一个线程看不到另一个线程修改的结果, 因为缓存还没有刷新到主内存的原因. volatile 关键字确保每次在做修改时都直接写入主内存(或同步高速缓存). 从而保障各个线程都能看到修改结果.

过潦 2022-09-18 18:47:20

可以参考这里:The Java® Language Specification Java SE 8 Edition

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

Some implementations may find it convenient to divide a single write action on a 64-bit long or double value into two write actions on adjacent 32-bit values. For efficiency's sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to perform writes to long and double values atomically or in two parts.

Implementations of the Java Virtual Machine are encouraged to avoid splitting 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.

在虚拟机规范中并没有规定对非 volatile 的 double 和 long 的读写是原子的,但是虚拟机的具体实现也可以是原子的,对于 volatile 修饰的,读写必须为原子的。

经测试,在 32 位的 intel 机器上,不是原子的,在 64 位的 intel 机器上是原子的

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文