std::counting_semaphore, std::binary_semaphore
定义于头文件 <semaphore> |
||
template< std::ptrdiff_t LeastMaxValue = /* implementation-defined */ > class counting_semaphore; |
(1) | (C++20 起) |
using binary_semaphore = std::counting_semaphore<1>; |
(2) | (C++20 起) |
counting_semaphore
是一种轻量级的同步原语,可以控制对共享资源的访问。与 std::mutex 不同,counting_semaphore
允许超过一个并发访问同一资源,至少 LeastMaxValue
个并发访问器。如果 LeastMaxValue
为负,则程序格式错误。binary_semaphore
是 std::counting_semaphore
的特化别名,其 LeastMaxValue
为 1。实现可以比 std::counting_semaphore
的默认实现更高效地实现 binary_semaphore
。一个 counting_semaphore
包含一个由构造函数初始化的内部计数器。此计数器在调用 acquire() 和相关方法时递减,并在调用 release() 时递增。当计数器为零时,acquire() 阻塞直到计数器递增,但 try_acquire() 不阻塞;try_acquire_for() 和 try_acquire_until() 阻塞直到计数器递增或达到超时。
类似于 std::condition_variable::wait(),counting_semaphore
的 try_acquire() 可能会虚假失败。
std::counting_semaphore
的特化不是 可默认构造的 (DefaultConstructible)、可拷贝构造的 (CopyConstructible)、可移动构造的 (MoveConstructible)、可拷贝赋值的 (CopyAssignable) 或 可移动赋值的 (MoveAssignable)。
目录 |
[编辑] 数据成员
成员名称 (Member name) | 定义 |
counter (私有) |
类型为 std::ptrdiff_t 的内部计数器。 (仅用于阐释的成员对象*) |
[编辑] 成员函数
构造一个 counting_semaphore (公共成员函数) | |
销毁 counting_semaphore (公共成员函数) | |
operator= [已删除] |
counting_semaphore 不可赋值(公共成员函数) |
操作 | |
增加内部计数器并解除阻塞获取器 (公共成员函数) | |
递减内部计数器或阻塞直到可以递减 (公共成员函数) | |
尝试递减内部计数器而不阻塞 (公共成员函数) | |
尝试递减内部计数器,阻塞一段持续时间 (公共成员函数) | |
尝试递减内部计数器,阻塞直到某一时间点 (公共成员函数) | |
常量 | |
[静态] |
返回内部计数器的最大可能值 (公共静态成员函数) |
[编辑] 注解
正如其名称所示,LeastMaxValue
是*最小*最大值,而不是*实际*最大值。因此 max() 可能返回大于 LeastMaxValue
的数字。
与 std::mutex 不同,counting_semaphore
不与执行线程绑定——例如,获取信号量可以在与释放信号量不同的线程上发生。所有对 counting_semaphore
的操作都可以并发执行,并且与特定的执行线程没有任何关系,除了析构函数不能并发执行但可以在不同线程上执行。
信号量也常用于信令/通知而不是互斥的语义,通过将信号量初始化为 0,从而阻塞尝试 acquire() 的接收者,直到通知者通过调用 release(n) 来“发出信号”。在这方面,信号量可以被视为 std::condition_variable 的替代方案,通常具有更好的性能。
特性测试宏 | 值 | 标准 | 特性 |
---|---|---|---|
__cpp_lib_semaphore |
201907L |
(C++20) | std::counting_semaphore , std::binary_semaphore |
[编辑] 示例
#include <chrono> #include <iostream> #include <semaphore> #include <thread> // global binary semaphore instances // object counts are set to zero // objects are in non-signaled state std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // wait for a signal from the main proc // by attempting to decrement the semaphore smphSignalMainToThread.acquire(); // this call blocks until the semaphore's count // is increased from the main proc std::cout << "[thread] Got the signal\n"; // response message // wait for 3 seconds to imitate some work // being done by the thread using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // message // signal the main proc back smphSignalThreadToMain.release(); } int main() { // create some worker thread std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // message // signal the worker thread to start working // by increasing the semaphore's count smphSignalMainToThread.release(); // wait until the worker thread is done doing the work // by attempting to decrement the semaphore's count smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // response message thrWorker.join(); }
输出
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal