std:: counting_semaphore, std:: binary_semaphore
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
| Operations | ||||
| Constants | ||||
|
定义于头文件
<semaphore>
|
||
|
template
<
std::
ptrdiff_t
LeastMaxValue
=
/* 由实现定义 */
>
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
。实现可能对
binary_semaphore
进行比
std::counting_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
的特化不满足
可默认构造
、
可复制构造
、
可移动构造
、
可复制赋值
或
可移动赋值
的要求。
目录 |
数据成员
| 成员名称 | 定义 |
counter
(private)
|
类型为
std::ptrdiff_t
的内部计数器。
( 仅用于说明的成员对象* ) |
成员函数
构造
counting_semaphore
(公开成员函数) |
|
析构
counting_semaphore
(公开成员函数) |
|
|
operator=
[deleted]
|
counting_semaphore
不可赋值
(公开成员函数) |
操作 |
|
|
递增内部计数器并解除获取者的阻塞
(公开成员函数) |
|
|
递减内部计数器或在无法递减时阻塞
(公开成员函数) |
|
|
尝试非阻塞地递减内部计数器
(公开成员函数) |
|
|
尝试递减内部计数器,最多阻塞一段时长
(公开成员函数) |
|
|
尝试递减内部计数器,阻塞直到某个时间点
(公开成员函数) |
|
常量 |
|
|
[static]
|
返回内部计数器的最大可能值
(公开静态成员函数) |
注释
正如其名称所示,
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> // 全局二进制信号量实例 // 对象计数设置为零 // 对象处于非触发状态 std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // 通过尝试减少信号量计数来等待主进程的信号 smphSignalMainToThread.acquire(); // 此调用将阻塞,直到主进程增加信号量计数 std::cout << "[thread] Got the signal\n"; // 响应消息 // 等待3秒以模拟线程正在执行某些工作 // 由线程完成 using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // 消息 // 向主进程发送信号 smphSignalThreadToMain.release(); } int main() { // 创建工作线程 std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // 消息 // 通过增加信号量计数通知工作线程开始工作 smphSignalMainToThread.release(); // 通过尝试减少信号量计数等待工作线程完成工作 smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // 响应消息 thrWorker.join(); }
输出:
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal