当前位置: 首页 > news >正文

C++ 20 信号量详解

C++ 20 信号量详解

一、信号量类型

C++20 标准中定义了两种信号量:

  1. std::counting_semaphore<Max>:计数信号量(允许资源池最多有 Max 个资源)
  2. std::binary_semaphore:二进制信号量(等价于 std::counting_semaphore<1>

二、代码实现与详解
1. 计数信号量(生产者-消费者模型)
#include <iostream>
#include <thread>
#include <semaphore>
#include <queue>
#include <mutex>// 最大缓冲区大小
constexpr size_t BUFFER_SIZE = 5;// 定义信号量(空位初始为5,数据初始为0)
std::counting_semaphore<BUFFER_SIZE> empty_slots(BUFFER_SIZE);
std::counting_semaphore<BUFFER_SIZE> data_items(0);std::mutex mtx;              // 保护共享队列的互斥锁
std::queue<int> buffer;       // 共享缓冲区
bool producer_done = false;  // 生产完成标志void producer() {for (int i = 1; i <= 10; ++i) {empty_slots.acquire(); // 等待空位{std::lock_guard<std::mutex> lock(mtx);buffer.push(i);std::cout << "Product: " << i << std::endl;}data_items.release(); // 增加数据项}// 生产完成后设置标志std::lock_guard<std::mutex> lock(mtx);producer_done = true;
}void consumer() {while (true) {data_items.acquire(); // 等待数据{std::lock_guard<std::mutex> lock(mtx);// 检查是否所有数据已消费if (producer_done && buffer.empty()) break;int val = buffer.front();buffer.pop();std::cout << "Consume: " << val << std::endl;}empty_slots.release(); // 释放空位}
}int main() {std::jthread prod(producer); // C++20 自动管理线程std::jthread cons(consumer);return 0;
}
2. 二进制信号量(互斥访问)
#include <iostream>
#include <thread>
#include <semaphore>std::binary_semaphore resource(1);  // 初始可用
int counter = 0;void worker(int id) {for (int i = 0; i < 3; ++i) {resource.acquire();  // P操作++counter;std::cout << "线程" << id << "修改计数器: " << counter << std::endl;resource.release();  // V操作std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}int main() {std::jthread t1(worker, 1);std::thread t2(worker, 2);t1.join();t2.join();return 0;
}

三、编译与运行
  1. 编译命令(需要支持C++20的编译器):

    g++ -std=c++20 -pthread -o semaphore_demo semaphore_demo.cpp
    
  2. 输出示例
    在这里插入图片描述


四、核心概念解析
  1. acquire()(P操作):

    • 减少信号量计数器
    • 若计数器为0则阻塞,直到有其他线程执行release()
  2. release()(V操作):

    • 增加信号量计数器
    • 唤醒等待中的线程(如果有)
  3. 二进制信号量特性

    • 初始值设为1时等价于互斥锁
    • 但释放操作可由任意线程执行(与互斥锁不同)

五、关键点总结
特性计数信号量二进制信号量
最大计数值模板参数指定(如<5>固定为1
典型应用场景资源池管理互斥访问/同步标志
线程唤醒策略先进先出(FIFO)取决于具体实现
内存占用每个实例约4-8字节同计数信号量

相关文章:

  • 梯度下降,共轭梯度,牛顿法,拟牛顿法的收敛速度对比
  • SAP 查找JOB进程ID
  • 05、GPIO外设(五):CubeMX配置
  • SQL:聚合函数(Aggregate Functions)
  • Java 接入deepseek(非流式)
  • 基于autoware.1.14与gazebo联合仿真进行激光点云循迹仿真
  • 基于领域知识的A型主动脉夹层综合分割及面向临床的评估|文献速递-深度学习医疗AI最新文献
  • 【学习笔记】文件上传漏洞--黑白盒审计
  • 文章记单词 | 第37篇(六级)
  • 云服务器和物理服务器
  • AI写程序: 多线程网络扫描网段ip工具
  • 内网穿透服务器—FRP
  • 颚式破碎机的设计
  • c# 简单实现将Message的内容保存到txt中,超过100个则清理旧文件
  • Linux:线程的同步与互斥(生产者消费者模型的demo)
  • Function Calling的时序图(含示例)
  • FA-YOLO:基于FMDS与AGMF的高效目标检测算法解析
  • C++指针与内存管理深度解析
  • TDengine Restful 接口API
  • 【机试】高精度
  • 西藏艺术来到黄浦江畔,“隐秘之门”艺术展外滩三号开幕
  • 上海崇明“人鸟争食”何解?检察机关推动各方寻找最优解
  • 商务部新闻发言人就美对我海事、物流和造船等领域宣布最终措施答记者问
  • 左眼失明左耳失聪,办理残疾人证被拒?县残联:双眼残疾才能办
  • 上海警方:男子拍摄女性视频后在网上配发诱导他人违法犯罪文字,被行拘
  • 工信部:加快推进6G技术研发等,前瞻布局和培育面向6G的应用产业生态