c++的std::barrier和std::latch是什么 C++20线程同步新工具【并发编程】
技术百科
冰火之心
发布时间:2026-01-21
浏览: 次 std::latch 是一次性倒计时门闩,初始化后通过 count_down() 减数、wait() 等待归零,不可重置;std::barrier 是可重复使用的同步栅栏,支持 arrive_and_wait() 等待全体到达并自动重置,还可指定回调函数。
std::barrier 和 std::latch 是 C++20 引入的两个轻量级线程同步原语,用于协调多个线程在某个点上等待或计数,比传统 std::mutex + std::condition_variable 更简洁、高效,且无状态重用限制(barrier 可重复使用,latch 仅单次)。
std::latch:一次性倒计时门闩
它像一个“一次性的门”,初始化时指定一个计数值(如 5),每次调用 count_down() 减一;当计数归零,所有正在 wait() 的线程被同时唤醒,之后再调用 wait() 会立即返回(不阻塞)。它不可重置、不可重复使用。
- 典型用途:主线程等待 N 个子线程完成初始化或某阶段任务(例如启动阶段齐步走)
- 构造后只能
count_down()、count_down(1)或wait(),不能增加计数 - 线程安全:所有成员函数都是无锁且线程安全的
- 示例:
std::latch ready(3);—— 3 个线程各调一次ready.count_down();,第 4 个线程调ready.wait();就会等到前 3 次完成才继续
std::barrier:可重复使用的同步栅栏
和 latch 类似,但支持重复使用。初始化时也指定参与线程数(如 4),每个线程调用 arrive_and_wait() 表示到达并等待其他线程;当第 N 个线程到达,所有线程同时被释放,并自动重置内部计数,准备下一轮同步。
- 典型用途:多线程循环计算中的每轮屏障(如迭代式算法、并行 pipeline 各阶段同步)
- 还提供
arrive()(仅计数,不等待)和带回调的arrive_and_drop()(到达后退出栅栏,减少后续参与数) - 回调函数(构造时传入)会在每次计数归零、所有线程释放前由其中一个线程执行(常用于汇总、刷新等操作)
- 示例:
std::barrier b(4, []{ std::cout —— 每凑够 4 个线程到达,就打印一次提示并重置
对比与选型建议
两者都基于无锁原子操作实现,开销远低于条件变量,也不依赖互斥量。区别核心在于生命周期:
- 用 latch 当你只需要“等一件事完成”(一次性信号),比如资源初始化完毕、测试开始前等待全部线程就绪
- 用 barrier 当你需要“反复等一组线程汇合”(循环同步),比如并行 for 循环中每轮迭代结束后的同步点
- 都不支持超时等待(C++20 中没有
try_wait_for等变体
),如有超时需求仍需回退到 condition_variable
- 二者头文件均为
,无需额外链接
注意事项
它们不是万能替代品:不提供线程间数据传递能力,也不保证内存顺序(需配合 std::memory_order 或显式 fence 使用);若需复杂逻辑(如条件唤醒、优先级等待),还是得用更底层的同步机制。
# ai
# 就会
# 都是
# 也不
# 当你
# 都不
# 迭代
# 工具
# 循环
# 并发
# c++
# 线程
# 回调
# 无锁
# 多线程
# 成员函数
# 算法
# 重复使用
# 回调函数
# 主线程
# 并发编程
# 倒计时
# 齐步走
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Python高性能计算项目教程_NumPyCyth
- php能控制zigbee模块吗_php通过串口与c
- 如何在Golang中实现CI/CD流水线自动化测试
- 如何在 Go 中判断变量是否为函数类型
- php本地部署支持nodejs吗_php与node
- Windows10电脑怎么设置虚拟内存_Win10
- c++ stringstream用法详解_c++字
- Win11怎么查看硬盘型号_Windows 11检
- Windows10系统怎么查看CPU核心数_Win
- Windows10电脑怎么设置文件权限_Win10
- ACF 教程:如何正确更新嵌套在多层 Group
- Win11怎么设置快速访问_Windows11文件
- php下载安装后memory_limit怎么设置_
- Win11怎么开启移动热点_Windows11共享
- php8.4如何配置ssl证书_php8.4htt
- 如何使用Golang实现RPC序列化与反序列化_G
- php怎么下载安装后无法解析php文件_服务器配置
- phpstudy本地环境mysql忘记密码_重置m
- 如何在Golang中实现微服务负载均衡_Golan
- Golang如何避免指针逃逸_Golang逃逸分析
- Go语言中slice追加操作的底层共享机制详解
- C++如何解析JSON数据?(nlohmann/j
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- Win11怎样安装微信开发者工具_Win11安装开
- 如何在 Go 开发中正确处理本地包导入与远程模块路
- C++如何使用Qt创建第一个GUI窗口?(入门教程
- Win11怎么关闭键盘按键音_Win11禁用打字声
- Win10路由器怎么隐藏ssid Win10隐藏w
- c++如何使用std::bind绑定函数参数_c+
- Win11怎么退出高对比度模式_Win11取消反色
- Win11蓝牙开关不见了怎么办_Win11蓝牙驱动
- Win11无法拖拽文件到任务栏怎么办_Win11开
- PHP cURL GET请求:正确设置请求头与身份
- Win10怎样清理C盘浏览器缓存_Win10清理浏
- c++中explicit(bool)的用法 c++
- 如何解决同一段404代码在不同主机上表现不一致的问
- Win11怎么设置鼠标宏_Win11鼠标按键自定义
- Win11输入法切换快捷键怎么改_Windows
- VSC里PHP变量未定义报错怎么解决_错误抑制技巧
- Win11输入法选字框不见了怎么办_Win11输入
- Go 中实现 Python urllib.quot
- Python性能剖析高级教程_cProfileLi
- mac怎么安装adb_MAC配置Android A
- Win11屏幕亮度突然变暗怎么解决_自动变暗问题处
- Win11怎么自动隐藏任务栏_Win11全屏显示设
- c++ nullptr与NULL区别_c++11空
- 使用类变量定义字符串常量时的类型安全最佳实践
- Win11怎么关闭任务栏小组件_Windows11
- Win11怎么设置默认输入法 Win11固定中文输
- Win10电脑怎么设置IP地址_Windows10


QQ客服