C
C 语法

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的修改顺序AB 之前发生。

请注意,虽然每个原子对象都有自己的修改顺序,但它不是总顺序; 不同的线程可以观察对不同顺序的不同原子对象的修改。

所有原子操作都有四种连贯性保证:

  • 写 - 写连贯性:如果修改原子对象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