std::atomic_thread_fence
定义于头文件 <atomic> |
||
extern "C" void atomic_thread_fence( std::memory_order order ) noexcept; |
(C++11 起) | |
根据 `order` 参数的要求,在不关联原子操作的情况下建立非原子和宽松原子访问的内存同步顺序。然而,请注意,至少需要一个原子操作来设置同步,如下所述。
目录 |
[编辑] 栅栏-原子同步
如果满足以下条件,线程 A 中的释放栅栏 F 与线程 B 中的原子获取操作 Y 同步:
- 存在一个原子存储 X(具有任何内存顺序),
- Y 读取 X 写入的值(或者如果 X 是释放操作,则为以 X 为首的释放序列将写入的值),
- 在线程 A 中,F 在 X 之前排序。
在这种情况下,在线程 A 中在 F 之前排序的所有非原子和宽松原子存储,将在线程 B 中在 Y 之后从相同位置进行的所有非原子和宽松原子加载 之前发生。
[编辑] 原子-栅栏同步
如果满足以下条件,线程 A 中的原子释放操作 X 与线程 B 中的获取栅栏 F 同步:
- 存在一个原子读取 Y(具有任何内存顺序),
- Y 读取 X 写入的值(或以 X 为首的释放序列写入的值),
- 在线程 B 中,Y 在 F 之前排序。
在这种情况下,在线程 A 中在 X 之前排序的所有非原子和宽松原子存储,将在线程 B 中在 F 之后从相同位置进行的所有非原子和宽松原子加载 之前发生。
[编辑] 栅栏-栅栏同步
如果满足以下条件,线程 A 中的释放栅栏 FA 与线程 B 中的获取栅栏 FB 同步:
- 存在一个原子对象 M,
- 存在一个原子写入 X(具有任何内存顺序),它在线程 A 中修改 M,
- 在线程 A 中,FA 在 X 之前排序,
- 在线程 B 中存在一个原子读取 Y(具有任何内存顺序),
- Y 读取 X 写入的值(或者如果 X 是释放操作,则为以 X 为首的释放序列将写入的值),
- 在线程 B 中,Y 在 FB 之前排序。
在这种情况下,在线程 A 中在 FA 之前排序的所有非原子和宽松原子存储,将在线程 B 中在 FB 之后从相同位置进行的所有非原子和宽松原子加载 之前发生。
[编辑] 参数
顺序 | - | 此栅栏执行的内存排序 |
[编辑] 返回值
(无)
[编辑] 注意
在 x86(包括 x86-64)上,`atomic_thread_fence` 函数不发出 CPU 指令,仅影响编译时代码移动,除了 std::atomic_thread_fence(std::memory_order_seq_cst)。
`atomic_thread_fence` 施加的同步约束比具有相同 std::memory_order 的原子存储操作更强。原子存储-释放操作阻止所有之前的读写操作越过存储-释放,而带有 std::memory_order_release 顺序的 `atomic_thread_fence` 阻止所有之前的读写操作越过所有随后的存储。
栅栏-栅栏同步可用于为一系列宽松原子操作添加同步,例如
// Global std::string computation(int); void print(std::string); std::atomic<int> arr[3] = {-1, -1, -1}; std::string data[1000]; //non-atomic data // Thread A, compute 3 values. void ThreadA(int v0, int v1, int v2) { // assert(0 <= v0, v1, v2 < 1000); data[v0] = computation(v0); data[v1] = computation(v1); data[v2] = computation(v2); std::atomic_thread_fence(std::memory_order_release); std::atomic_store_explicit(&arr[0], v0, std::memory_order_relaxed); std::atomic_store_explicit(&arr[1], v1, std::memory_order_relaxed); std::atomic_store_explicit(&arr[2], v2, std::memory_order_relaxed); } // Thread B, prints between 0 and 3 values already computed. void ThreadB() { int v0 = std::atomic_load_explicit(&arr[0], std::memory_order_relaxed); int v1 = std::atomic_load_explicit(&arr[1], std::memory_order_relaxed); int v2 = std::atomic_load_explicit(&arr[2], std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_acquire); // v0, v1, v2 might turn out to be -1, some or all of them. // Otherwise it is safe to read the non-atomic data because of the fences: if (v0 != -1) print(data[v0]); if (v1 != -1) print(data[v1]); if (v2 != -1) print(data[v2]); }
[编辑] 示例
扫描邮箱数组,只处理为我们准备的邮箱,无需不必要的同步。此示例使用原子-栅栏同步。
const int num_mailboxes = 32; std::atomic<int> mailbox_receiver[num_mailboxes]; std::string mailbox_data[num_mailboxes]; // The writer threads update non-atomic shared data // and then update mailbox_receiver[i] as follows: mailbox_data[i] = ...; std::atomic_store_explicit(&mailbox_receiver[i], receiver_id, std::memory_order_release); // Reader thread needs to check all mailbox[i], but only needs to sync with one. for (int i = 0; i < num_mailboxes; ++i) if (std::atomic_load_explicit(&mailbox_receiver[i], std::memory_order_relaxed) == my_id) { // synchronize with just one writer std::atomic_thread_fence(std::memory_order_acquire); // guaranteed to observe everything done in the writer thread // before the atomic_store_explicit() do_work(mailbox_data[i]); }
[编辑] 另请参阅
(C++11) |
定义给定原子操作的内存排序约束 (enum) |
(C++11) |
线程与在同一线程中执行的信号处理程序之间的屏障 (function) |
C 文档 for atomic_thread_fence
|