Namespaces
Variants

std:: barrier

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
barrier
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
定义于头文件 <barrier>
template < class CompletionFunction = /* see below */ >
class barrier ;
(C++20 起)

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

屏障对象的生命周期包含一个或多个阶段。每个阶段定义一个 阶段同步点 ,等待线程会在此阻塞。线程可以通过调用 arrive 到达屏障但延迟等待 阶段同步点 。此类线程后续可通过调用 wait 阶段同步点 上阻塞。

屏障的 阶段 包含以下步骤:

  1. 每次调用 arrive arrive_and_drop 时, 期望计数 会递减。
  2. 当期望计数降为零时,将执行 阶段完成步骤 ,即调用 completion ,并解除所有在阶段同步点阻塞的线程。完成步骤的结束 强发生于 所有因完成步骤而解除阻塞的调用返回之前。
    在期望计数达到零后,某个线程在其调用 arrive arrive_and_drop wait 期间会精确执行一次完成步骤,但若没有线程调用 wait ,该步骤是否执行由实现定义。
  3. 当完成步骤结束时,期望计数被重置为构造时指定的值减去自那时起对 arrive_and_drop 的调用次数,并开始下一个 屏障阶段

barrier 成员函数(析构函数除外)的并发调用不会引入数据竞争。

目录

模板参数

CompletionFunction - 函数对象类型
-
CompletionFunction 必须满足 MoveConstructible Destructible 的要求。 std:: is_nothrow_invocable_v < CompletionFunction & > 必须为 true

CompletionFunction 的默认模板实参是一个未指定的函数对象类型,该类型额外满足 可默认构造 要求。调用其左值无参版本不产生任何效果。

成员类型

名称 定义
arrival_token 满足 MoveConstructible MoveAssignable Destructible 要求的未指定对象类型

数据成员

成员 定义
CompletionFunction completion 在每次阶段完成步骤时调用的完成函数对象
( 仅用于说明的成员对象* )

成员函数

构造一个 barrier
(公开成员函数)
销毁 barrier
(公开成员函数)
operator=
[deleted]
barrier 不可赋值
(公开成员函数)
到达屏障并递减期望计数
(公开成员函数)
在阶段同步点阻塞,直到其阶段完成步骤运行
(公开成员函数)
到达屏障并将期望计数减一,然后阻塞直到当前阶段完成
(公开成员函数)
将后续阶段的初始期望计数和当前阶段的期望计数各减一
(公开成员函数)
常量
[static]
实现支持的期望计数的最大值
(公开静态成员函数)

注释

功能测试 标准 功能
__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;  // 正确,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)
一次性线程屏障
(类)