std::barrier

来自cppreference.com
< cpp‎ | thread
 
 
并发支持库
线程
(C++11)
(C++20)
(C++20)
this_thread 命名空间
(C++11)
(C++11)
(C++11)
互斥
(C++11)
(C++11)  
通用锁管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
条件变量
(C++11)
信号量
闩与屏障
(C++20)
barrier
(C++20)
未来体
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(C++26)
(C++26)
风险指针





原子类型
(C++11)
(C++20)
原子类型的初始化
(C++11)(C++20 中弃用)
(C++11)(C++20 中弃用)
内存定序
原子操作的自由函数
原子标志的自由函数
 
 
在标头 <barrier> 定义
template< class CompletionFunction = /* 见下文 */ >
class barrier;
(C++20 起)

类模板 std::barrier 提供一种线程协调机制,阻塞已知大小的线程组直至该组中的所有线程到达该屏障。不同于 std::latch,屏障是可重用的:一旦到达的线程组被解除阻塞,即可重用同一屏障。与 std::latch 不同,会在线程解除阻塞前执行一个可能为空的可调用对象。

屏障对象的生存期由一个或多个屏障阶段组成。每个阶段定义一个阻塞线程的阶段同步点。线程可以抵达屏障,但通过调用 arrive 来推迟它在阶段同步点上的等待。这样的线程可以随后再通过调用 wait阶段同步点上阻塞。

屏障 阶段 由以下步骤组成:

  1. 每次调用 arrivearrive_and_drop 减少期待计数
  2. 期待计数抵达零时,运行阶段完成步骤,即调用 completion,并解除所有在阶段同步点上阻塞的线程。完成步骤的结束强先发生于所有从完成步骤所除阻的调用的返回。
    在期待计数抵达零后,一个线程会在其调用 arrivearrive_and_dropwait 的过程中执行完成步骤恰好一次,但如果没有线程调用 wait 则是否执行完成步骤为实现定义。
  3. 完成步骤结束时,重置期待计数为构造中指定的值,它可能为 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)
单次使用的线程屏障
(类)