【发布时间】:2017-03-10 17:00:21
【问题描述】:
这是对另一个 question of mine 的跟进。
@templatetypedef 回答了这个问题(赞赏),他在回答中写道:
请注意 - 原子性并不意味着“所有其他线程都将被阻塞 直到值准备好。这意味着所有其他线程要么会看到 纯粹在操作完成之前或纯粹之后的状态 操作已完成,但没有其他内容。
我对此感到困惑,原因如下:
上面写着here:
原子动作不能交错,因此可以放心使用 线程干扰。
我由此推断,与他所写的相矛盾。
如果我们有2个int变量i1和i2,我们做原子操作i1=i2;,这个操作由threadX执行。
如果原子操作不能像上面指出的那样交错,这意味着在这个原子操作期间(由 threadX 执行),不允许其他 threadY 访问(读取或写入)同一个变量 i2,因此,没有其他threadY 允许在原子操作期间访问同一个变量,因此确实存在某种形式的阻塞。
我做对了吗?
谢谢...
【问题讨论】:
-
不,这意味着 threadY 将看到 all 的分配,或 none 的分配......它不会看到“ i2 的几位,以及 i1 先前值的几位。
-
@Jon Skeet,所以如果你说的是真的,那么这句话:“原子动作不能交错,所以可以使用它们而不用担心线程干扰。”是 flase,因为在原子操作 i1=i2 期间,threadX 和 threadY 可能会在相同的数据(本例中为 i2)上交错。我明白你的观点 threadY 将始终在原子操作之前或之后读取值,但如果在原子操作期间允许 threadY 读取 i2 i1=i2;然后threadX和threadY在i2上交错,但是根据Oracle教程是不可能的,我错过了什么吗?
-
Reading i2(或者,通常是来自不同 CPU 缓存的 i2 的单独副本)不能构成交错,因为即使它发生在同一个挂钟时间。 在同一挂钟时间在不同线程中写入 i2 不构成交错,如果最终结果是“i1=i2”获得完整的旧 i2 值或完整的新 i2 值,因为它与另一个线程在“i1=i2”之前或之后执行操作的行为一致,因此这不是在原子操作中间交错,它只会导致不同的顺序。
-
关于“...可以使用而不必担心线程干扰...”的引用并不能说明全部情况。当我们谈论“线程安全”时,我们必须在架构的每一层谈论它。由于此处已经讨论过的原因,对
int变量的读取和写入是线程安全的,但这不会自动使使用 int 变量的算法成为线程安全的。而且,如果您采取必要的步骤来确保算法的安全性,那并不能确保调用您的算法的代码的安全性,以此类推。
标签: java multithreading atomic