std::barrier 是用于多线程同步的原语,使指定数量线程在某点集体等待齐后继续执行;适用于并行迭代、分块处理等需阶段性同步的场景,需正确初始化计数并确保每线程调用 arrive_and_wait()。

std::barrier 是什么,什么时候该用它
它不是互斥锁,也不是条件变量,而是专门用来让一组线程在某个点“集体暂停、等齐了再一起往下走”的同步原语。典型场景是:多个工作线程并行处理一批数据的某一轮,必须全部完成当前轮次后,才能启动下一轮——比如并行数值迭代、分块图像处理、多阶段模拟步进。
别把它当 std::mutex 用,也别指望它保护共享变量;它只管“到齐就放行”,不带所有权或临界区语义。
怎么正确初始化和等待 barrier
std::barrier 构造时必须指定参与线程数(即“等几个人”),这个数不能改,也不能动态增减。一旦所有线程调用 arrive_and_wait(),屏障就重置,可重复使用。
常见错误:
立即学习“C++免费学习笔记(深入)”;
- 传错计数:比如用
std::thread::hardware_concurrency()当作实际启动的线程数,但实际只起了 3 个线程,却初始化为 8——那剩下 5 个永远等不到,程序卡死 - 漏调用:某个线程因为异常、提前 return 或逻辑分支没走到
arrive_and_wait(),整个组就挂住 - 跨线程复用未重置的 barrier 实例:C++20 的
std::barrier是可重用的,但前提是所有线程都已完成上一轮等待;没人帮你检查“是否真等齐了”,靠代码逻辑保证
示例(4 个线程同步三轮):
吉他谱教学视频教学网站源码是基于易优cms开发,适合做吉他乐谱在线学习网站使用,内核为Thinkphp5.0开发,后台简洁,为吉他音乐学习而设计开发,这是一套安装就能建站的程序,不定期更新程序BUG,更新网站功能。 我们提供的不仅是源码模板这么简单,我们还提供程序相关咨询、协助安装等服务。 默认不包含小程序插件,需要另外单独购买插件。 模板安装步骤 1、请将安装包Z
std::barrier b{4};
for (int round = 0; round < 3; ++round) {
// 各线程做本轮计算...
do_work(round);
// 全部到这里等齐
b.arrive_and_wait(); // 注意:不是 arrive() + wait() 分开调
}
barrier 和 latch、semaphore 的关键区别
std::barrier 是“可重用的、固定人数的同步点”;std::latch 是“一次性倒计时门闩”,到达零就永远打开;std::counting_semaphore 更底层,支持 acquire/release、可超量 release,但没内置“全体到齐”语义。
选错会出问题:
- 想做多轮同步却用了
std::latch:第一轮完就失效,第二轮调wait()会直接返回,失去同步效果 - 用
std::counting_semaphore模拟 barrier:得自己维护计数+广播逻辑,容易漏唤醒或重复唤醒,还可能因 acquire 失败抛异常 -
std::barrier不提供异常安全的 arrive:如果某线程在arrive_and_wait()前抛异常,其他线程仍在等,程序 hang 住——必须确保 arrive 调用一定发生
Windows / macOS / GCC 版本兼容性注意点
std::barrier 是 C++20 标准特性,但落地有温差:
- GCC 11+ 默认启用,但需编译选项
-std=c++20(仅-std=c++17不行) - Clang 12+ 支持,macOS 上需 Xcode 13.3+(对应 libc++ 13.0)
- MSVC 19.30+(VS 2022 17.0)才完整支持,早期预览版可能缺少
arrive_and_drop()等扩展方法
如果你的项目还要兼容 GCC 10 或旧 MSVC,别硬上 std::barrier——要么降级用 std::condition_variable + 计数器手写,要么引入 boost.thread 的 boost::barrier(行为最接近)。
真正麻烦的不是语法写不对,而是跨平台 CI 里某个编译器静默忽略 barrier 或链接失败,而本地开发环境刚好跑得通。









