0

0

c++的std::barrier如何用于实现多线程的集合点同步? (栅栏)

穿越時空

穿越時空

发布时间:2026-01-13 12:59:02

|

763人浏览过

|

来源于php中文网

原创

std::barrier是C++20引入的循环同步原语,适用于多线程分阶段协作场景,如并行计算的每轮迭代同步;它支持自动重置,需精确指定并确保恰好N个线程调用wait()。

c++的std::barrier如何用于实现多线程的集合点同步? (栅栏)

std::barrier 是什么,适合在哪种同步场景用

std::barrier 是 C++20 引入的线程同步原语,专为「多个线程在某个点集体等待、全部到达后才一起继续」这种集合点(rendezvous)场景设计。它比 std::condition_variable + std::mutex 更轻量,也比反复轮询或 std::latch(仅能触发一次)更贴合循环协作模式。

典型适用场景:多线程并行计算中需要分阶段执行,比如每轮迭代开始前所有线程必须完成上一轮工作;或模拟物理仿真中每个时间步所有线程更新完状态再统一推进。

如何正确构造和调用 barrier.wait()

构造时需指定预期到达的线程数(expected),该值不可变。每次调用 barrier.wait() 会阻塞当前线程,直到第 expected 个线程抵达 —— 此时所有等待线程被同时唤醒,且 barrier 自动重置为下一轮等待(这是它和 std::latch 的关键区别)。

  • 必须确保**恰好**有 expected 个线程调用 wait(),少一个会永久挂起,多一个会触发未定义行为(通常 crash 或死锁)
  • 同一个 std::barrier 对象可被重复使用,无需重建
  • 不支持超时等待(C++20 标准中无 try_wait_for 等变体),如需超时需自行封装
std::barrier b{4}; // 期待 4 个线程到达
std::vector threads;
for (int i = 0; i < 4; ++i) {
    threads.emplace_back([&b, i] {
        // 每个线程做些事
        do_work(i);
        // 到达集合点
        b.wait(); // 阻塞直到第 4 个线程也调用 wait()
        // 所有线程在此处之后并发继续
        continue_processing(i);
    });
}
for (auto& t : threads) t.join();

为什么不能用 std::latch 替代 barrier 实现循环同步

std::latch 是一次性门闩:构造时设 count,每次 count_down() 减一,减到零后所有等待者被唤醒,但之后再调用 wait() 会立即返回,无法重置。而 std::barrier 在每次全员到达后自动归零并重置计数器,天然适配多轮同步。

墨狐AI
墨狐AI

5分钟生成万字小说,人人都是小说家!

下载

立即学习C++免费学习笔记(深入)”;

  • 若强行用 std::latch 做多轮同步,你得在每轮开始前 new 一个新 latch,或手动管理生命周期,极易出错
  • std::barrierarrive() 成员函数允许提前通知到达(不阻塞),配合 wait() 可实现更灵活的协调逻辑(例如某些线程只报告不等待)
  • 底层实现上,barrier 通常比反复构造 latch 更高效,避免内存分配和销毁开销

常见误用与崩溃原因

实际写代码时最容易栽在生命周期和调用次数上:

  • std::barrier 对象必须**在线程调用 wait() 期间持续有效** —— 如果它是个局部变量,而主线程在子线程还在 wait() 时就退出了作用域,会导致未定义行为(常见 SIGSEGV)
  • 误把 barrier.arrive() 当作 wait() 使用:前者只递减计数并返回新计数值,不阻塞;若只调 arrive() 不调 wait(),其他线程会在 wait() 处永远等不到第 expected 个到达
  • 跨线程传递 barrier 时用了裸指针或引用,但源对象已析构,尤其在 lambda 捕获时容易忽略捕获方式:[&b][b] 安全,但更要确保 b 的生存期覆盖所有线程

复杂点在于:barrier 的语义干净,但它的正确性完全依赖程序员对线程数量和生命周期的手动保证,编译器和运行时几乎不帮你检查。稍不留神,就是静默死锁或随机崩溃。

相关专题

更多
counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

205

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

190

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

50

2026.01.05

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

143

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

11

2026.01.21

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

4

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号