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

C++20中的counting_semaphore的应用

一、std::counting_semaphore

在前面介绍过C++20中的同步库,其中就提到过std::counting_semaphore。但当时的重点是同步库的整体介绍,本文则会对std::counting_semaphore这个信号量进行一个全面的分析和说明,并有针对性的给出具体的例程。
C++20中对其的定义为:

template< std::ptrdiff_t LeastMaxValue = /* implementation-defined */ >
class counting_semaphore;
using binary_semaphore = std::counting_semaphore<1>;

LeastMaxValue值并不实际最大值,即此值是可以被突破的。

二、应用说明

要想掌握好std::counting_semaphore,如果能够在学习操作系统时将其中的PV原语理解的很透彻,那么这就不是什么问题了。所以推荐大家如果不清楚的可以回头先看一看什么是PV原语。
std::counting_semaphore作为一个轻量级的同步原语,主要是用来对共享资源的控制,与互斥体等的不同,其允许对同一资源进行指定数量的线程同步访问。怎么说呢,其实就是C++标准中的同步控制,在以前基本只能同一情况下访问同一资源(其它库如Posix,windows平台等)。可能大牛们觉得已经够用了,但在其它语言都推出了信号灯及其类似的同步原语,而且随着C++应用的不断发展,应该是大牛们觉得还是要提供一下类似的实现(这只是个人猜测)。
counting_semaphore提供了一个指定线程同步访问的数量,而binary_semaphore则可以理解成前者的一个特化例子,只支持0,1两种状态,有点类似于互斥体,但它没有所有权一说。这样应用到一些特定的场景时不用调用复杂的counting_semaphore。
std::counting_semaphore与普通的Mutex一个重要的不同在于,与线程的所有权控制不同,前者不会绑定到指定的线程,也即任何一个线程都可以进行获取和释放信号量,请开发者一定要明白。
其最典型的两个接口为:
1、std::counting_semaphore::release
原子性的按Update增加内部计数器,即增加信号量。当然update的值需要大于等0且小于等于最大值-当前计数器大小。
2、std::counting_semaphore::acquire
原子性的将内部计数器减1,前提是内部计数器大于0;否则将阻塞线程,直到计数器超过0。

这里有一个需要注意的情况,counting_semaphore在信号的下限即0时,调用acquire,不会出现异常问题;但在到达上限时,再调用release,则会出现UB行为。这点非常重要。
如果大家想扩展一下视野,还可以看看其它库或平台中的类似的semaphore的实现,也可以看看其它语言(如Java等)中类似的实现,就可以更好的理解信号量的应用。

三、例程

看一下cppreference上的例程:

#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_semaphoresmphSignalMainToThread{0},smphSignalThreadToMain{0};void ThreadProc()
{// wait for a signal from the main proc// by attempting to decrement the semaphoresmphSignalMainToThread.acquire();// this call blocks until the semaphore's count// is increased from the main procstd::cout << "[thread] Got the signal\n"; // response message// wait for 3 seconds to imitate some work// being done by the threadusing namespace std::literals;std::this_thread::sleep_for(3s);std::cout << "[thread] Send the signal\n"; // message// signal the main proc backsmphSignalThreadToMain.release();
}int main()
{// create some worker threadstd::thread thrWorker(ThreadProc);std::cout << "[main] Send the signal\n"; // message// signal the worker thread to start working// by increasing the semaphore's countsmphSignalMainToThread.release();// wait until the worker thread is done doing the work// by attempting to decrement the semaphore's countsmphSignalThreadToMain.acquire();std::cout << "[main] Got the signal\n"; // response messagethrWorker.join();
}

运行结果:

[main] Send the signal
[thread] Got the signal
[thread] Send the signal
[main] Got the signal

四、总结

大牛陈硕曾经说过,实际的编程场景基本用不到semaphore,如果真用到了,极有可能设计上有问题。他的这个说法本人非常赞同。建议在实际场景中尽量还是谨慎使用这种信号量,不过,在某些特定的场景下,如果确实是需要使用信号量,或者整体考虑代价要小于其它方法的情况下,也不是不可以使用。
仍然是前面反复提到的,合适的就是最好的。技术本身没有绝对的好与坏!

http://www.lryc.cn/news/580325.html

相关文章:

  • C++ 模板参数匹配、特化
  • AtCoder AT_abc413_c [ABC413C] Large Queue 题解
  • Oracle 数据库——企业级核心系统
  • MySQL(118)如何使用SSL进行加密连接?
  • mysql的备份与恢复(使用mysqldump)
  • pyinstaller打包教程
  • TCP数据的发送和接收
  • 闲庭信步使用SV搭建图像测试平台:第三十一课——基于神经网络的手写数字识别
  • Ubuntu基础(监控重启和查找程序)
  • 模块三:现代C++工程实践(4篇)第一篇《C++模块化开发:从Header-only到CMake模块化》
  • Redis的编译安装
  • LabVIEW电阻率测试
  • LinkedList剖析
  • Kafka消息积压全面解决方案:从应急处理到系统优化
  • idea的使用小技巧,个人向
  • 类图+案例+代码详解:软件设计模式----适配器模式
  • 【电赛培训】运算放大器、滤波器
  • 使用 C++/OpenCV 和 MFCC 构建双重认证智能门禁系统
  • 堆的简单介绍
  • 智链万物:人工智能驱动的产业智能化革命
  • 使用 C++/Faiss 加速海量 MFCC 特征的相似性搜索
  • Python(28)Python循环语句指南:从语法糖到CPython字节码的底层探秘
  • 解决el-select数据类型相同但是显示数字的问题
  • 【Project】基于kafka的高可用分布式日志监控与告警系统
  • C#扩展方法全解析:给现有类型插上翅膀的魔法
  • CMake基础:条件判断详解
  • 探索 Ubuntu 上 MongoDB 的安装过程
  • [Cyclone] 哈希算法 | SIMD优化哈希计算 | 大数运算 (Int类)
  • 【大模型】到底什么是Function Calling和MCP,以及和ReAct推理的关系是什么?
  • 若 VSCode 添加到文件夹内右键菜单中显示