c++ c++20 std::latch用法 c++如何用latch同步多个线程

冬伟酱_7517

冬伟酱_7517

2026-03-19

158人浏览

原创

std::latch初始化值必须等于count_down()总调用次数;设为0则wait立即返回,设小会导致ub,设大则永久阻塞;它不可重用、不支持超时和中断,且需严格保证跨线程生命周期安全。

c++ c++20 std::latch用法 c++如何用latch同步多个线程

std::latch 初始化值必须等于等待线程数

初始化 std::latch 时传的整数,是它内部计数器的初始值,不是“要等几个线程”,而是“要 count_down() 多少次才变零”。如果开 5 个线程,每个都调一次 count_down(),就得初始化为 5。设成 1 或 0,要么提前唤醒,要么永远卡死。

  • 设成 0:构造完就已就绪,wait() 立刻返回 —— 这不是 bug,但容易误以为“没生效”
  • 设成 3 但有 5 个线程调 count_down():第 4 次调用会 UB(未定义行为),Clang/GCC 在 debug 模式下可能 abort
  • 典型场景:主线程启动 N 个 worker 线程,每个 worker 完成后调一次 count_down(),主线程 wait() 等全部结束

std::latch 不可重用,用完即弃

std::latch 是一次性同步原语。一旦计数器归零,wait() 总是立即返回,count_down() 不再改变状态,也不能 reset 或重新设置计数。想重复同步,得 new 一个新对象,或者换用 std::barrier。

  • 错误写法:latch.wait(); latch.count_down(); latch.wait(); —— 第二个 wait() 不阻塞
  • 替代方案:std::barrier 支持 arrive_and_wait() 循环使用,但需显式指定参与方数量且不能动态增减
  • 性能提示:std::latch 通常比 std::condition_variable 轻量,无锁实现常见,适合一等多、不重入的场景

std::latch 在线程间传递需注意生命周期

把 std::latch 对象传给子线程时,必须确保它在所有线程调用 count_down() 或 wait() 期间始终有效。局部变量直接传引用?大概率 crash。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 安全做法:堆上分配(std::shared_ptr<:latch></:latch>),或作为类成员/全局对象管理生命周期
  • 危险写法:std::thread{[&latch] { latch.count_down(); }};,其中 latch 是栈变量且主线程很快退出作用域
  • 错误现象:子线程访问已析构的 latch,触发 SIGSEGV 或静默内存破坏,调试困难
  • C++20 要求 std::latch 是 trivially destructible,但它内部可能持有原子变量或系统句柄,析构非空操作

std::latch wait() 不响应中断,也不支持超时

std::latch::wait() 是纯阻塞调用,没有 wait_until() 或 wait_for() 变体,也没办法被信号、取消请求或异常中断。一旦卡住,只能靠外部机制(比如共享 flag + try_wait() 轮询)来保底。

  • 若需超时:手动轮询 try_wait() 配合 std::this_thread::sleep_for(),但失去原子性优势
  • try_wait() 是无副作用的只读检查,返回 bool 表示当前是否已就绪
  • 对比 std::condition_variable:虽更重,但支持精确超时和 notify_one/notify_all 粒度控制
  • 实际建议:仅用于“确定能完成”的短时协作;长期任务或需容错的场景,别硬扛 wait()

最易忽略的是生命周期和初始化值的耦合关系:值设错不会编译报错,运行时表现却完全失控,而且问题在线程交织下难以复现。写完先盯两眼构造参数和谁在哪儿调 count_down()。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

5847

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2508

6

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

5847

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2508

6

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

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

2023.08.10

4218

6

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

2025.12.01

543

16

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

2026.10.16

60

10

OpenJDK怎么配置Java开发环境
OpenJDK怎么配置Java开发环境

怎样用OpenJDK搭建开发环境?本专题介绍版本选择、下载安装、环境变量配置和编译运行验证,帮助你理清JDK的作用及基本配置流程,并通过简单程序检查环境是否可用,为后续项目开发做好准备。

2026.10.16

40

10

OpenJDK怎么部署Java应用
OpenJDK怎么部署Java应用

Java项目开发完成后,怎样部署到目标环境并正常运行?本专题介绍OpenJDK应用部署流程,涵盖运行环境准备、版本兼容检查、应用打包、启动参数配置和日志查看,帮助你理清部署前后的操作顺序,减少环境差异造成的运行问题。

2026.10.16

40

10

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习