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

【Linux】线程POSIX信号量

目录

1. 整体学习思维导图

2. 信号量的概念

3. 基本接口

4. 基于环形队列的生产者消费者模型(信号量)


1. 整体学习思维导图

2. 信号量的概念

POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。但

POSIX可以用于线程间同步。

POSIX信号量的本质是一个计数器,是对特定资源的预定机制!我们之前在进程通信时已经做了了解!

  • 多线程使用资源,有两种场景:

    • 将目标资源整体使用 【Mutex + 二元信号量】

    • 将目标资源划分为不同的"块",分批使用【信号量】 --> 电影院的观影座位售卖

  • 信号量一旦申请成功,就会保证该线程一定有块资源可以使用!(预定机制的体现)

  • 所有线程都需要看到sem信号量,因此信号量是临界资源。

  • PV操作需要是原子性的:

    • P:--

    • V: ++

3. 基本接口

1. 初始化信号量:sem_t sem; sem_init(&sem, 0, 1);&sem 是信号量指针。0 表示信号量用于线程间同步(1 表示进程间同步)。1 是信号量的初始值。2. P 操作:sem_wait(&sem);3. V 操作:sem_post(&sem);4. 销毁信号量:sem_destroy(&sem);
  • Sem.hpp 封装

#include <iostream>
#include <semaphore.h>
#include <pthread.h>namespace SemModule
{const int defaultvalue = 1;class Sem{public:Sem(unsigned int sem_value = defaultvalue){sem_init(&_sem, 0, sem_value);}void P(){int n = sem_wait(&_sem); // 原子的(void)n;}void V(){int n = sem_post(&_sem); // 原子的}~Sem(){sem_destroy(&_sem);}private:sem_t _sem;};
}

4. 基于环形队列的生产者消费者模型(信号量)

 

  • 实现单生产者/单消费者模型

    • P C --> p与c之间互斥和同步关系由信号量维持

  • 实现多生产者/多消费者模型

    • PP CC --> pp/cc之间的互斥关系需要维持 --> Mutex加锁 Enqueue/Pop

    • 因此我们需要两边锁,一把锁解决pp,一把锁解决cc

问题:先申请信号量,还是先加锁?

应该先申请信号量,有了信号量说明该对象将执行对应的Enqueue/Pop操作,再让有了信号量的对象竞争锁访问临界资源,这样排除了没有对应信号量执行操作的对象。如果先加锁,会导致拥有信号量的对象想要访问临界资源时的锁被没有信号量不需要执行操作的对象拿到了锁,从而造成死锁问题。

  1. 信号量筛选有效线程:只有持有信号量的线程才有资格竞争锁。

  2. 锁保证操作原子性:避免多个线程同时修改队列。

  3. 避免死锁:防止无效线程占用锁导致资源饥饿。

  • 代码实现:

#pragma once#include <iostream>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"static const int gcap = 5; // for debugusing namespace SemModule;
using namespace MutexModule;template <typename T>
class RingQueue
{
public:RingQueue(int cap = gcap): _cap(cap),_rq(cap),_blank_sem(cap),_p_step(0),_data_sem(0),_c_step(0){}void Equeue(const T &in){// 生产者// 1. 申请信号量,空位置信号量_blank_sem.P();{LockGuard lockguard(_pmutex);// 2. 生产_rq[_p_step] = in;// 3. 更新下标++_p_step;// 4. 维持环形特性_p_step %= _cap;}_data_sem.V();}void Pop(T *out){// 消费者// 1. 申请信号量,数据信号量_data_sem.P();{LockGuard lockguard(_cmutex);// 2. 消费*out = _rq[_c_step];// 3. 更新下标++_c_step;// 4. 维持环形特性_c_step %= _cap;}_blank_sem.V();}private:std::vector<T> _rq;int _cap;// 生产者Sem _blank_sem; // 空位置int _p_step;// 消费者Sem _data_sem; // 数据int _c_step;// 维护多生产,多消费, 2把锁Mutex _cmutex;Mutex _pmutex;
};

相关文章:

  • 【Linux基础】程序和软件安装管理命令
  • MindSpore框架学习项目-ResNet药物分类-模型评估
  • 天线的PCB设计
  • 理性地倾听与表达:检索算法的语言学改进
  • SpringBoot学习(上) , SpringBoot项目的创建(IDEA2024版本)
  • [架构之美]IntelliJ IDEA创建Maven项目全流程(十四)
  • OpenVLA:开源的视觉-语言-动作模型
  • torch.nn.init.uniform_
  • 大模型微调终极方案:LoRA、QLoRA原理详解与LLaMA-Factory、Xtuner实战对比
  • 数仓-可累计,半累加,不可累加指标,是什么,举例说明及解决方案
  • 前端项目中单元测试与集成测试的管理实践
  • 【数据结构】子串、前缀
  • QT Creator配置Kit
  • Windows系统Jenkins企业级实战
  • 大模型Embedding模型介绍与使用
  • 【生命周期分析(Life Cycle Assessment: LCA)】基于OpenLCA、GREET、R语言的生命周期评价方法、模型构建及典型案例应用
  • Redisson 看门狗机制
  • 【大数据技术-HBase-关于Hmaster、RegionServer、Region等组件功能和读写流程总结】
  • 第五天 车载系统安全(入侵检测、OTA安全) 数据加密(TLS/SSL、国密算法)
  • Taccel:一个高性能的GPU加速视触觉机器人模拟平台
  • 普京提议于15日在土耳其恢复俄乌直接谈判
  • 宣布停火后,印控克什米尔地区再次传出爆炸声
  • 国常会:研究深化国家级经济技术开发区改革创新有关举措等
  • 欧盟决意与俄罗斯能源彻底决裂之际,美国谋划新生意:进口俄气对欧转售
  • 正荣地产:董事会主席、行政总裁辞任,拟投入更多精力推动境内债重组等工作
  • 光大华夏:近代中国私立大学遥不可及的梦想