std::latch是一次性同步原语,用于等待指定数量的操作完成,计数归零后唤醒所有等待线程且不可重用;std::barrier是可重用同步原语,支持多轮阶段性汇合,并可选抵达回调函数。

std::barrier 和 std::latch 是 C++20 引入的两个轻量级同步原语,用于协调多个线程在某个点“汇合”(synchronize),但用途和生命周期有本质区别:前者可重用、后者一次性。
std::latch:一次性的“门闩”
std::latch 用来等待一组操作全部完成。它内部维护一个计数器,初始值由构造函数指定;每次调用 count_down() 计数器减一;当计数器归零,所有阻塞在 wait() 的线程被唤醒——且之后无法重置或复用。
典型场景:主线程启动多个工作线程,等它们全部初始化完毕再统一开始执行。
- 构造时传入期望的线程数(如
std::latch ready(4)表示等 4 次count_down) - 各线程完成准备后调用
ready.count_down() - 主线程调用
ready.wait()阻塞,直到计数为 0 - 不能重复使用,也不能增加计数;用完即弃
std::barrier:可重复使用的“路障”
std::barrier 也基于计数,但它支持“阶段式同步”——所有线程到达后一起通过,然后自动重置计数器,进入下一轮等待。适合循环协作场景,比如多线程迭代计算。
立即学习“C++免费学习笔记(深入)”;
它还支持可选的“抵达后回调”(arrival phase function),在最后一名线程抵达、所有线程释放前执行一次(常用于汇总、交换数据等)。
- 构造时指定参与线程数,例如
std::barrier sync(4) - 每个线程调用
sync.arrive_and_wait()—— 先抵达,再阻塞,等全员到齐才返回 - 若需在同步点做全局操作,可用带回调的构造:
std::barrier sync(4, []{ /* 每轮同步前执行一次 */ }); - 无需手动管理状态,自动循环,适合多轮协作
别混淆:latch vs barrier 的关键区别
二者名字相似,但设计目标不同:
- std::latch 是“等待完成”——像发令枪前的起跑线,所有人就位后只响一次
- std::barrier 是“阶段性汇合”——像接力赛每一段的交接区,每轮都清空重来
- latch 没有回调,barrier 可配回调;latch 不可重用,barrier 天然可重用
- 两者都不拥有线程,也不负责线程创建/销毁,只是同步点
实际用法小提醒
它们头文件都是 ,注意编译器需支持 C++20(如 GCC 10+、Clang 11+、MSVC 19.28+),并开启 -std=c++20。
不推荐用它们替代 mutex 或 condition_variable 做细粒度互斥;它们解决的是“集体行动步调一致”的问题,不是“保护共享数据”。用错场景反而引入竞态或死锁。
基本上就这些。不复杂但容易忽略细节——记清“一次”还是“多次”,就能选对工具。










