为什么像fetch-and-add这样的原子操作会返回被更改的变量的旧值?

时间:2016-04-07 18:27:19

标签: java multithreading opengl atomic atomicity

我正在努力学习并更好地理解多线程,但我对原子函数(如fetch-and-add)的行为感到困惑。在fetch-and-add的特定情况下,我理解一个值(假设当前等于5的x)被一个增量值(比如说3)加上,结果sum(8)被写入x的放在内存中,但返回旧的值(5)。

在不同的地方还有其他几个这样的函数(比如OpenGL的原子函数,Java的AtomicIntegers,还有更多的区域)就像这样。但我不明白的是为什么代码中的一个地方想要写入内存但仍然首先返回它想要修改的值。任何人都可以帮助阐明这一点吗?

3 个答案:

答案 0 :(得分:4)

答案很简单。原子函数的本质是它们修改(在这种情况下增加)执行时的实际值 ,这可能与代码知道的值不同。

示例:

x = 5; // x is global
y = atomically_increment(x);
// what is y? 

现在,如果x恰好在增量实际发生之前从5变为6,则y将等于6,x将变为9。

答案 1 :(得分:2)

扩展谢尔盖的答案......

我认为fetch-and-add类似于信号量;除了fetch-and-add调用使一切都成为原子操作。以下是显示原始值使用的算法示例:http://research.omicsgroup.org/index.php/Ticket_lock

答案 2 :(得分:1)

获取和添加指令或操作(如x86的XADD)可以避免执行CAS循环并提供预期的初始值。

但是这也意味着在你的代码中,在fetch-and-add成功之后,你不知道增加了什么值,并且在重大争用下,在获取和添加之前读取值可能仍然远离事实。这就是为什么因原子提取和添加而返回旧值或新值非常有用。

例如,Aeron使用fetch-and-add返回的值来确定是否应该旋转其缓冲区(请参阅https://youtu.be/eKVpea51tvo?t=31m54s)。