理解C++20中的std::counting_semaphore和std::binary_semaphore

Lobsters Hottest 工具

摘要

本文讲解C++20的std::counting_semaphore和std::binary_semaphore,涵盖其API、用于限制并发和线程间信号传递的用法,以及重要细节。

<p><a href="https://lobste.rs/s/safj18/understanding_std_counting_semaphore">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/08/08 22:38

# 理解 C++20 的 std::counting_semaphore 和 std::binary_semaphore Source: https://www.cppstories.com/2026/semaphore/ ## 目录 - 基础 (https://www.cppstories.com/2026/semaphore/#basics) - API (https://www.cppstories.com/2026/semaphore/#api) - 使用 `std::counting_semaphore` 限制并发 (https://www.cppstories.com/2026/semaphore/#limiting-concurrency-with-stdcounting_semaphore) - 使用 RAII 归还槽位 (https://www.cppstories.com/2026/semaphore/#returning-a-slot-with-raii) - 使用 `std::binary_semaphore` 进行信令 (https://www.cppstories.com/2026/semaphore/#signaling-with-stdbinary_semaphore) - 带超时的等待 (https://www.cppstories.com/2026/semaphore/#waiting-with-a-timeout) - 信号量、互斥量还是条件变量? (https://www.cppstories.com/2026/semaphore/#semaphore-mutex-or-condition-variable) - 值得了解的细节 (https://www.cppstories.com/2026/semaphore/#details-worth-knowing) - `LeastMaxValue` 是一个下界 (https://www.cppstories.com/2026/semaphore/#leastmaxvalue-is-a-lower-bound) - 不要将计数器增加到 `max()` 以上 (https://www.cppstories.com/2026/semaphore/#do-not-increase-the-counter-past-max) - `try_acquire()` 可能假性失败 (https://www.cppstories.com/2026/semaphore/#try_acquire-may-fail-spuriously) - 不保证等待顺序 (https://www.cppstories.com/2026/semaphore/#waiting-order-is-not-guaranteed) - 注意生命周期 (https://www.cppstories.com/2026/semaphore/#watch-the-lifetime) - 总结 (https://www.cppstories.com/2026/semaphore/#summary) - 参考 (https://www.cppstories.com/2026/semaphore/#references) 本文解释了 C++20 中引入的两种信号量类型:`std::counting_semaphore` 和 `std::binary_semaphore`。我们首先使用计数信号量来限制同一时间可以操作的线程数量。然后使用二进制信号量在线程之间发送信号。我们还会探讨超时等待、一个小型 RAII 辅助类以及其他一些细节。 > **注意:** 这里讨论的同步功能在 C++20 中可用。示例使用 C++23 的 `std::println` 以得到更清晰的输出。我们开始吧。 ## 基础 互斥量在每次只允许一个线程进入受保护区域时效果很好。但有时这个限制过于严格。想象一个应用程序拥有三个数据库连接。如果每次只运行一个数据库操作,就会浪费其中两个连接。另一方面,允许任意数量的线程开始操作可能会使数据库过载。我们需要的是一种限制:三个线程可以继续执行,而其余线程等待。 还有另一种常见情况。一个线程准备数据,另一个线程等待数据就绪。信号量可以很好地解决这两个问题。许多多线程库都有信号量,但 C++20 标准库现在直接提供了信号量,这非常酷。 ## API 计数信号量声明为: `std::counting_semaphore` 主要操作如下: | 函数 | 描述 | |------|------| | `counting_semaphore(desired)` | 创建计数器设置为 `desired` 的信号量 | | `acquire()` | 减少计数器;如果为零则等待

相似文章

C++ 非对称内存栅栏的细节

Hacker News Top

深入探讨 C++ 并发中的非对称线程栅栏,涵盖 C++ 提案 P1202R0 及其通过 Linux membarrier() 系统调用的实现,并附有来自 Folly 同步原语的示例。

使用:counters和:atomics模块在Erlang中快速计数

Hacker News Top

这篇技术文章解释了如何使用Erlang的:counters和:atomics模块进行高性能计数和共享可变状态,从而突破标准的进程隔离模型。内容涵盖BEAM运行时中的原子操作,如add_get、exchange和compare-and-swap(比较并交换)。

C++26:更多函数包装器

Lobsters Hottest

C++26 引入了两个新的函数包装器:std::copyable_function(提供了可复制且 const 正确的 std::function 替代品)和 std::function_ref(一个非拥有、可调用的引用,具有引用语义)。

Thoroughly Understanding C++ ABI

Hacker News Top

A deep dive into C++ ABI, explaining binary interface concepts, CPU/OS dependencies, object file formats like ELF and PE32+, and calling conventions.

C语言中的Go风格并发

Hacker News Top

一篇详细的技术文章,探讨如何在C语言中复制Go的并发模型,使用POSIX线程、互斥锁、条件变量和工作池,作为Solod转译器项目的一部分。