std::barrier
| 
 在标头  
<barrier> 定义 | 
||
| 
 template< class CompletionFunction = /* 见下文 */ > 
class barrier;  | 
(C++20 起) | |
类模板 std::barrier 提供一种线程协调机制,阻塞已知大小的线程组直至该组中的所有线程到达该屏障。不同于 std::latch,屏障是可重用的:一旦到达的线程组被解除阻塞,即可重用同一屏障。与 std::latch 不同,会在线程解除阻塞前执行一个可能为空的可调用对象。
屏障对象的生存期由一个或多个屏障阶段组成。每个阶段定义一个阻塞线程的阶段同步点。线程可以抵达屏障,但通过调用 arrive 来推迟它在阶段同步点上的等待。这样的线程可以随后再通过调用 wait 在阶段同步点上阻塞。
屏障 阶段 由以下步骤组成:
- 每次调用 
arrive或arrive_and_drop减少期待计数。 - 期待计数抵达零时,运行阶段完成步骤,即调用 
completion,并解除所有在阶段同步点上阻塞的线程。完成步骤的结束强先发生于所有从完成步骤所除阻的调用的返回。
在期待计数抵达零后,一个线程会在其调用arrive、arrive_and_drop或wait的过程中执行完成步骤恰好一次,但如果没有线程调用wait则是否执行完成步骤为实现定义。 - 完成步骤结束时,重置期待计数为构造中指定的值,它可能为 
arrive_and_drop调用所调整,自此开始下一阶段。 
并发调用barrier 除了析构函数外的成员函数不会引起数据竞争。
模板形参
| CompletionFunction | - | 函数对象类型 | 
-
CompletionFunction 必须满足可移动构造 (MoveConstructible) 和 可析构 (Destructible) 。std::is_nothrow_invocable_v<CompletionFunction&> 必须为 true。 | 
||
CompletionFunction 的默认模板实参是未指定的函数对象类型,它还满足可默认构造 (DefaultConstructible) 。以无实参调用其左值无效果。
成员对象
| 名称 | 定义 | 
 completion (私有) | 
CompletionFunction 类型的完成函数对象,在每个阶段完成步骤调用。(仅用于阐述的成员对象*)  | 
成员类型
| 名称 | 定义 | 
arrival_token | 
未指定的对象类型,满足可移动构造 (MoveConstructible) 、可移动赋值 (MoveAssignable) 及可析构 (Destructible) | 
成员函数
构造 barrier(公开成员函数)  | 
|
销毁 barrier(公开成员函数)  | 
|
| 
 operator= 
[弃置] 
 | 
barrier 不可赋值(公开成员函数)  | 
| 到达屏障并减少期待计数 (公开成员函数)  | 
|
| 在阶段同步点阻塞,直至运行其阶段完成步骤 (公开成员函数)  | 
|
| 到达屏障并把期待计数减少一,然后阻塞直至当前阶段完成 (公开成员函数)  | 
|
| 将后继阶段的初始期待计数和当前阶段的期待计数均减少一 (公开成员函数)  | 
|
常量 | 
|
| 
 [静态] 
 | 
实现所支持的期待计数的最大值 (公开静态成员函数)  | 
注解
| 功能特性测试宏 | 值 | 标准 | 功能特性 | 
|---|---|---|---|
__cpp_lib_barrier | 
201907L | (C++20) | std::barrier | 
| 202302L | (C++20) (DR)  | 
放松的阶段完成保证 | 
示例
#include <barrier> #include <iostream> #include <string> #include <syncstream> #include <thread> #include <vector> int main() { const auto workers = {"Anil", "Busara", "Carl"}; auto on_completion = []() noexcept { // 此处无需锁定 static auto phase = "... 完成\n" "清理...\n"; std::cout << phase; phase = "... 完成\n"; }; std::barrier sync_point(std::ssize(workers), on_completion); auto work = [&](std::string name) { std::string product = " " + name + " 已工作\n"; std::osyncstream(std::cout) << product; // OK, op<< 的调用是原子的 sync_point.arrive_and_wait(); product = " " + name + " 已清理\n"; std::osyncstream(std::cout) << product; sync_point.arrive_and_wait(); }; std::cout << "启动...\n"; std::vector<std::jthread> threads; threads.reserve(std::size(workers)); for (auto const& worker : workers) threads.emplace_back(work, worker); }
可能的输出:
启动... Anil 已工作 Carl 已工作 Busara 已工作 ... 完成 清理... Busara 已清理 Carl 已清理 Anil 已清理 ... 完成
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 | 
|---|---|---|---|
| P2588R3 | C++20 | 旧的阶段完成保证可能阻碍硬件加速 | 已放松 | 
参阅
| 
 (C++20) 
 | 
单次使用的线程屏障 (类)  |