types
原子类型
句法
_Atomic ( type-name ) | (1) | (since C11) |
---|---|---|
_Atomic type-name | (2) | (since C11) |
1)用作类型说明符; 这指定了一种新的原子类型
2)用作类型限定词; 这指定了类型名称的原子版本。在这个角色中,它可能与 const,volatile 和 restrict混合使用),但与其他限定符不同,type-name 的原子版本可能具有不同的大小,对齐和对象表示。
type-name | - | any type other than array or function. For (1), type-name also cannot be atomic or cvr-qualified |
---|
头<stdatomic.h>定义37层便于使用的宏,从atomic_bool到atomic_uintmax_t,这简化使用这个关键字与内置和库类型的。
_Atomic const int * p1; // p is a pointer to an atomic const int
const atomic_int * p2; // same
const _Atomic(int) * p3; // same
说明
原子类型的对象是唯一没有数据竞争的对象,也就是说,它们可以被两个线程同时修改或修改一个并被另一个线程修改。
每个原子对象都有自己的关联修改顺序
,这是对该对象进行修改的总顺序。如果从某个线程的角度来看,A
某些原子M的修改发生在修改B
相同的原子 M 之前,那么按M的修改顺序
,A
在 B
之前发生。
请注意,虽然每个原子对象都有自己的修改顺序,但它不是总顺序; 不同的线程可以观察对不同顺序的不同原子对象的修改。
所有原子操作都有四种连贯性保证:
写 - 写连贯性
:如果修改原子对象M的操作A发生在
修改M的操作B之前
,则A按修改顺序M出现在B之前
。
一些原子操作也是同步操作; 他们可能会有额外的释放语义,获取语义或顺序一致的语义。看memory_order
。
内置增量和减量运算符和复合赋值是按顺序一致的顺序进行读 - 修改 - 写原子操作(就像使用一样memory_order_seq_cst
)。如果需要较不严格的同步语义,则可以使用标准库函数。
原子属性只对左值表达式有意义。左值到右值转换(将从原子位置读到CPU寄存器的内存建模)与其他限定符一起剥离原子性。
笔记
如果宏常量__STDC_NO_ATOMICS__(C11)由编译器定义,则不提供关键字_Atomic和标题<stdatomic.h>。
访问原子结构/联合的成员是未定义的行为。
库类型sig_atomic_t
不提供线程间同步或内存排序,只有原子性。
易失性类型不提供线程间同步,内存排序或原子性。
关键词
_Atomic
.
例
#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>
atomic_int acnt;
int cnt;
int f(void* thr_data)
{
for(int n = 0; n < 1000; ++n) {
++cnt;
++acnt;
// for this example, relaxed memory order is sufficient, e.g.
// atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed
}
return 0;
}
int main(void)
{
thrd_t thr[10];
for(int n = 0; n < 10; ++n)
thrd_create(&thr[n], f, NULL
for(int n = 0; n < 10; ++n)
thrd_join(thr[n], NULL
printf("The atomic counter is %u\n", acnt
printf("The non-atomic counter is %u\n", cnt
}
可能的输出:
The atomic counter is 10000
The non-atomic counter is 8644