C语言 gcc 原子内置函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6786284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
gcc atomic built-in functions
提问by ddoman
http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html
http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html
I believe that the following code increases the value of var atomically.
我相信以下代码会原子地增加 var 的值。
volatile int var = 0;
__sync_fetch_and_add( &var, 1 )
I understood the above codes as the following logic:
我将上述代码理解为以下逻辑:
- Load the address of variable var
- write number 1 onto variable var atomically - through register/cache, somehow
- 加载变量var的地址
- 将数字 1 原子地写入变量 var - 通过寄存器/缓存,不知何故
However, I doubt if the following is atomic, too
但是,我怀疑以下是否也是原子的
volatile int var = 0;
volatile int num = 1;
__sync_fetch_and_add( &var, num )
Since it may be interpreted as
因为它可以被解释为
- Load the address of variable var
- Load the value of variable num into a register
- write the value onto variable var.
- 加载变量var的地址
- 将变量 num 的值加载到寄存器中
- 将值写入变量 var。
After #2 is executed, but before #3, the CPU/thread gets interrupted and another CPU/thread updates the value of variable num.
在#2 执行之后,#3 之前,CPU/线程被中断,另一个CPU/线程更新变量num 的值。
In other words, when using _sync*() of gcc, can I use a variable, not a constant, as the second argument?
换句话说,当使用_同步*()的gcc,我可以使用一个变量,而不是一个常数,作为第二个参数?
Doesn't it break the atomicity?
它不会破坏原子性吗?
回答by Dietrich Epp
The operation is really two operations.
该操作实际上是两个操作。
__sync_fetch_and_add( &var, num )
Loading numis atomic. Adding it to varis atomic. But two atomic operations do not make an atomic operation when put together. This is why it is so hard to invent new lock-free data structures. In general, two thread-safe operations do not necessarily make a thread-safe operation when composed.This is the reason why it is so difficult to make correct multithreaded applications.
加载num是原子的。添加它var是原子的。但是两个原子操作放在一起时不会构成原子操作。这就是为什么很难发明新的无锁数据结构。 通常,两个线程安全操作在组合时不一定构成线程安全操作。这就是为什么制作正确的多线程应用程序如此困难的原因。
You see, __sync_fetch_and_addis indeedatomic, but it behaves like an ordinary function -- so it takes the current value of "num" as a parameter. It is not quite correct to say the atomicity of the function is broken -- because it is the responsibility of the caller to load the value from num, and it's not part of the function's interface. I could equally complain about this:
你看,__sync_fetch_and_add确实是原子的,但它的行为就像一个普通的函数——所以它把“num”的当前值作为参数。说函数的原子性被破坏并不完全正确——因为从 加载值是调用者的责任num,而不是函数接口的一部分。我同样可以抱怨这个:
__sync_fetch_and_add(&var, some_really_long_function());
Or worse,
或者更糟的是,
__sync_fetch_and_add(long_function_1(), long_function_2());
You say it "may be interpreted as"
你说它“可能被解释为”
- Load the address of variable var
- Load the value of variable num
- Perform the atomic addition
- 加载变量var的地址
- 加载变量 num 的值
- 执行原子加法
But according to the C spec, it's not that it maybe interpreted this way, but rather, it mustbe interpreted this way, otherwise the compiler would not be conformant (actually, it could swap #1 and #2, but that's not important here).
但是根据C规范,并不是说可以这样解释,而是必须这样解释,否则编译器将不符合(实际上,它可以交换#1和#2,但这并不重要这里)。

