volatile变量的读 - 修改 - 写操作如何是线程安全的

问题描述 投票:2回答:1

我正在阅读JCIP并且无法理解3.3.1中的以下陈述,

只要您可以确保volatile变量仅从SINGLE线程写入,就可以安全地对共享的volatile变量执行读 - 修改 - 写操作。在这种情况下,您将修改限制在单个线程以防止竞争条件,并且volatile变量的可见性保证可确保其他线程查看最新值。

即使volatile变量只是从单个线程写入,它怎么能不提高竞争条件?如果线程A在counter++为1时执行counter,则线程B可以在counter+1写回内存之前进入并获得counter的陈旧值1。如何确保“防止竞争条件”和“其他线程看到最新的价值”?

附:我知道有同样的问题here,但我没有找到任何令人满意的答案。

java multithreading
1个回答
4
投票

volatile变量的读 - 修改 - 写操作如何是线程安全的

一般来说,他们不能。

您引用的文字说:

“只要能确保volatile变量只从SINGLE线程写入,就可以安全地对共享的volatile变量执行读 - 修改 - 写操作。”

这不是线程安全的意思。作为一般性陈述。

即使volatile变量只是从单个线程写入,它怎么能不提高竞争条件?

那么,读取线程没有竞争条件,因为它们只能看到最近写入的变量值。写线程由正常的执行规则控制,因此线程与自身之间不存在竞争条件。

如何确保“防止竞争条件”?

往上看。如果有多个线程更新,您只能参加比赛。从竞争条件的定义来看,这是不言而喻的。

[和]“其他线程看到最新的价值”?

这是Java内存模型指定volatile的结果。读取volatile变量可以保证看到任何线程最近一次写入的值。

如果线程A在计数器为1时执行计数器++,则线程B可以在计数器+ 1被写回内存之前进入,并获得计数器的失效值1。

在那种情况下,没有竞争条件。线程B看到最近写的counter值。该计数器尚未更新。这意味着count++不是原子的。但线程安全和原子并不意味着相同的事情。 Atomic是一个更有力的保证。而且JLS明确指出count++不是挥发性物质的原子。

现在(很明显)如果你的应用程序有多个共享的volatile变量由不同的(单个)线程更新,那么之前段落的简单推理可能会崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.