POSIX信号量以及读写者模型/环形队列

news2024/10/7 0:50:25

POSIX信号量

POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步,他的本质是一个计数器,对共享资源进行等待或释放


POSIX信号量的重要概念

1.计数器:信号量维护一个计数器,它表示当前可用的资源数量

2.释放 P操作:  尝试将信号量的值减1。如果信号量的值大于0,则减1并继续执行。如果信号量的值为0,则阻塞等待,直到信号量的值大于0。

3.等待 V操作:将信号量的值加1。如果有线程或进程在等待信号量,则唤醒其中一个。



POSIX信号量的种类

二元信号量:当计数器只能为1或0时,就是一个互斥锁,0就是阻塞,1就是非阻塞

计数信号量:当计数器大于1时,表示资源的可用数量,这个计数器表示可以同时访问共享资源的线程或进程的数量


POSIX信号量API使用

头文件包括

#include <semaphore.h>

1.sem_init

 sem_init用于初始化信号量计数器的多少

int sem_init(sem_t *sem, int pshared, unsigned int value);

 sem: 指向信号量的指针

pshared: 决定是否在进程间共享 若为0 则在线程进行共享 若不为0 则在进程之间共享

value: 信号量的多少 决定为二元信号量还是计数信号量

2.sem_wait

sem_wait(sem_t * sem)

对信号量进行P操作,等待

sem:指向信号量的指针

3.sem_post

sem_post(sem_t * sem)

对信号量进行V操作,释放

sem:指向信号量的指针

4.sem_destroy

 int sem_destroy(sem_t *sem);

销毁一个信号量

sem:指向信号量的指针


环形队列

这里的环形队列是基于生产者消费模型实现的

如图所示

如图是一个环形队列,生产者和消费者都是顺时针走,白色代表没有数据,黑色代表有数据, 生产者在消费者前生产,消费者在生产者后消费,这就是生产消费模型的环形队列

根据上文讲述的信号量

我们就可以把环形队列中的资源用信号量划

也就是_consumer_data=4   _product_data=4

那么也就是说 

1.只有_consumer_data>0时,生产者才能生产

2.只有_product_data>0时,消费者才能进行消费

对生产者与消费者之间的关系进行一个总结

消费者与消费者-----------互斥

生产者与生产者-----------互斥

生产者与消费者-----------互斥 无需维护

这里需要单独讲解一下,为什么生产者与消费者之间的互斥是无需维护的呢,

很简单,因为生产者和消费者永远都不会访问到同一块资源!!!

因为在环形队列中,生产者消费者访问同一块数据的时候就是环形队列为全空,或者全满的时候

如图:


实现

为了实现环形队列,我们需要用到两个锁,以及用一个vector来维护环形队列,另外在单独标记生产者和消费者的下标

    std::vector<T> _ring_queue;
    int _cap; // 环形队列的容量上限

    // 2. 生产和消费的下标
    int _productor_step;
    int _consumer_step;

    // 3. 定义信号量
    sem_t _product_sem; // 生产者关心
    sem_t _consumer_sem; // 消费者关心

    // 4. 定义锁,维护多生产多消费之间的互斥关系
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;

入队列(生产行为)

分为三个步骤

1.申请信号量 2.竞争生产锁 3.进行生产

 void Enqueue(const T &in)
    {
        // 生产行为
        P(_room_sem);
        Lock(_productor_mutex);
        // 一定有空间!!!
        _ring_queue[_productor_step++] = in; // 生产
        _productor_step %= _cap;
        Unlock(_productor_mutex);
        V(_data_sem);
    }

这里需要注意的是

进行生产任务的时候,我们只需对_productor_step进行%操作便可以进行环形操作了,这个操作我也在之前的设计循环队列中有所讲解算法题详解:设计循环队列-CSDN博客

出队列(消费行为)

1.申请信号量 2.竞争消费锁 3.进行消费

void Pop(T *out)
    {
        // 消费行为
        P(_data_sem);
        Lock(_consumer_mutex);
        *out = _ring_queue[_consumer_step++];
        _consumer_step %= _cap;
        Unlock(_consumer_mutex);
        V(_room_sem);
    }

 与生产行为相似,只需如法炮制便可

代码

#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

// 单生产,单消费
// 多生产,多消费
// "321":
// 3: 三种关系
// a: 生产和消费互斥和同步
// b: 生产者之间:
// c: 消费者之间:
// 解决方案:加锁
// 1. 需要几把锁?2把
// 2. 如何加锁?
template<typename T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }
    void Lock(pthread_mutex_t &mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void Unlock(pthread_mutex_t &mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
public:
    RingQueue(int cap): _ring_queue(cap), _cap(cap),  _productor_step(0), _consumer_step(0)
    {
        sem_init(&_product_sem, 0, _cap);
        sem_init(&_consumer_sem, 0, 0);

        pthread_mutex_init(&_productor_mutex, nullptr);
        pthread_mutex_init(&_consumer_mutex, nullptr);
    }
    void Enqueue(const T &in)
    {
        // 生产行为
        P(_product_sem);
        Lock(_productor_mutex);
        // 一定有空间!!!
        _ring_queue[_productor_step++] = in; // 生产
        _productor_step %= _cap;
        Unlock(_productor_mutex);
        V(_consumer_sem);
    }
    void Pop(T *out)
    {
        // 消费行为
        P(_product_sem);
        Lock(_consumer_mutex);
        *out = _ring_queue[_consumer_step++];
        _consumer_step %= _cap;
        Unlock(_consumer_mutex);
        V(_consumer_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&_product_sem);
        sem_destroy(&_consumer_sem);

        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }
private:
    // 1. 环形队列
    std::vector<T> _ring_queue;
    int _cap; // 环形队列的容量上限

    // 2. 生产和消费的下标
    int _productor_step;
    int _consumer_step;

    // 3. 定义信号量
    sem_t _product_sem; // 生产者关心
    sem_t _consumer_sem; // 消费者关心

    // 4. 定义锁,维护多生产多消费之间的互斥关系
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1835649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI大佬都在说下一个爆点是智能体,建议开发者抢占先机!

现在大模型行至一年&#xff0c;风口与炒作如影随形&#xff0c;相信很多人身处其中但仍然感到很迷失&#xff0c;这个行业到底发展到什么程度了&#xff0c;作为普通开发者还有什么可以抓住的机会&#xff1f;从AI大佬的观点中&#xff0c;我们能获得一些行业变化的新风向。 …

corona渲染器与vray比哪个好?支持云渲染平台吗

​在视觉渲染技术领域&#xff0c;V-Ray和Corona都以其卓越的性能和广泛应用赢得了高度评价。这两款渲染器各有其独特的优势&#xff0c;使得在它们之间做出选择并非易事。不同的应用场景和用户需求可能会让它们各自展现出不同的优势。 一、corona渲染器跟vray怎么样 在比较V-…

Paragon NTFS For Mac 15软件下载_Paragon NTFS For Mac 15官网最新版下载

Paragon NTFS For Mac 15是一款强大的Mac读写工具。paragon ​​ntfs for mac​​​中文版为您轻松解决Mac不能识别 Windows NTFS文件难题&#xff0c;简单自如读写NTFS外置存储文件。在Mac OS X下全读/写访问NTFS的任何分区&#xff0c;paragon ntfs for mac中文版实现在Windo…

java 面试题--基础

文章目录 基础java SE 、 EE 、 ME 的区别jdk 和 jre 区别&#xff1f;java 的日志级别基本数据类型 特性关键字finalabstractsuperswitchfortry catch 接口和抽象类的区别接口抽象类适用场景 类的加载循序静态代码块 传参问题访问修饰符运算符 反射java 里的应用为什么反射的性…

Cascadia Code 字体

维护一个很老的程序&#xff0c;打开了尘封已久的 Visual Studio 2010&#xff0c;默认的字体看着非常不舒服&#xff0c;于是更换了一下字体。当尝试更换成 Cascadia Code 字体之后&#xff0c;一下子舒服了。 之前比较习惯 Consolas 字体&#xff0c;以后记住了&#xff0c;C…

音乐管理系统 SpringBoot + vue

文章目录 1、简要介绍2、数据库设计3、解决的问题1、图片和音频的上传和存储2、分页功能 4、数据返回 也算是进行了半个学期&#xff0c;跟着老师讲的进行 后端使用SpringBoot 前端 vue layui jdk 18 项目地址&#xff1a;gitee 1、简要介绍 只有管理端&#xff0c;但是对用…

俄罗斯ozon爆款推荐丨ozon学生受众产品

在俄罗斯电商平台OZON上&#xff0c;学生受众是一个庞大且活跃的群体。为了满足他们的需求&#xff0c;OZON平台上涌现出了一系列受学生欢迎的爆款产品。以下是一些针对学生受众的OZON爆款推荐&#xff1a; OZON选品工具&#xff1a;D。DDqbt。COM/74rD Top1 UNO纸牌游戏 俄语…

线程本地化存储如何保证线程安全

线程本地化存储如何保证线程安全 1、背景2、详细分析1、背景 在并发编程中,可能最害怕听到一个词就是线程不安全。因为它意味着程序运行的时候,可能出现数据的读取或写入不准确等情况发生, 2、详细分析 可能对于每个工程师来说都不陌生,就是我们工作中常见的一个环节,…

图片怎么弄成黑白的?关于将图片改成黑白的几种方法

图片怎么弄成黑白的&#xff1f;黑白照片以其独特的艺术魅力和经典的视觉效果&#xff0c;依然在摄影和图像处理中占据重要地位。无论是为了追求怀旧的氛围&#xff0c;还是为了突出图像的构图和光影效果&#xff0c;许多人都希望将彩色图片转换成黑白图片。这不仅可以赋予图像…

Tomcat Websocket应用实例研究

概述 本文介绍了如何根据Tomcat给出的websocket实例&#xff0c;通过对实例的学习&#xff0c;定制自己基于websocket的应用。 环境及版本&#xff1a; Ubuntu 22.04.4 LTSApache Tomcat/10.1.20openjdk 11.0.23 2024-04-16浏览器&#xff1a;Chrome 相关资源及链接 Class…

大模型精调:实现高效迁移学习的艺术

在人工智能领域&#xff0c;大型预训练模型&#xff08;以下简称“大模型”&#xff09;已经取得了令人瞩目的成果。这些模型通过在海量数据上进行预训练&#xff0c;能够捕捉到丰富的特征信息&#xff0c;为各种下游任务提供强大的支持。然而&#xff0c;如何将这些大模型应用…

如何用Vue3打造一个炫酷的树状图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 Vue.js 的 Treemap 可视化组件 应用场景介绍 Treemap 可视化组件是一种强大的工具&#xff0c;用于以直观的方式展示分层数据。它将数据点绘制为矩形&#xff0c;其中每个矩形的大小与数据点的大小成正比…

【牛客面试必刷TOP101】Day33.BM70 兑换零钱(一)和BM71 最长上升子序列(一)

文章目录 前言一、BM70 兑换零钱(一)题目描述题目解析二、BM71 最长上升子序列(一)题目描述题目解析总结 前言 一、BM70 兑换零钱(一) 题目描述 描述&#xff1a; 给定数组arr&#xff0c;arr中所有的值都为正整数且不重复。每个值代表一种面值的货币&#xff0c;每种面值的货币…

C++ 60 之 虚析构和纯虚析构

#include <iostream> #include <string> #include <cstring> using namespace std;class Animal13{ public:Animal13(){cout << "Animal的默认构造函数" << endl;}virtual void speak(){cout << "动物叫" << en…

SD卡可以格式化成NTFS吗 SD卡Mac怎么读取内容

SD卡作为便携式存储媒介&#xff0c;广泛应用于我们的日常生活与工作之中。而NTFS&#xff0c;作为一种先进的文件系统&#xff0c;因其强大的功能和安全性&#xff0c;在Windows平台备受青睐。然而&#xff0c;当谈及将SD卡格式化为NTFS这一话题时&#xff0c;用户的疑惑随之而…

每日一练:攻防世界:Ditf

这是难度1的题吗&#xff1f;&#xff1f;&#xff1f; 拿到一个png图片&#xff0c;第一反应就是CRC爆破&#xff0c;结果还真的是高度被修改了 这里拿到一个字符串&#xff0c;提交flag结果发现不是&#xff0c;那么只可能是密钥之类的了 看看有没有压缩包&#xff0c;搜索…

超图论文细品——2019年AAAI《Hypergraph Neural Networks》

我是“导航” 1 摘要1.1 简介1.2 问题描述 2 超图2.1 图和超图对比 参考 1 摘要 1.1 简介 文章提出了一种名为超图神经网络的框架&#xff0c;用于高维数据的表示学习。 该方法英文称呼为 Hypergraph Neural Networks&#xff0c;简写为 HGNN。 1.2 问题描述 传统的 GNN 是…

多模态大模型通用模式

MM-LLMs&#xff08;多模态大模型&#xff09;是目前比较新的和实用价值越发显著的方向。其指的是基于LLM的模型&#xff0c;具有接收、推理和输出多模态信息的能力。这里主要指图文的多模态。 代表模型&#xff1a;GPT-4o、Gemini-1.5-Pro、GPT-4v、Qwen-VL、CogVLM2、GLM4V、…

服务器测试之硬盘规格扫盲贴

最近整理了AVL系统里的SSD相关规格信息&#xff0c;来个了解硬盘规格信息的扫盲贴,过程很曲折&#xff0c;但是认为学习一下相关规格参数还是很有用的 1.什么是硬盘 硬盘是计算机最主要的存储设备&#xff0c;平常买电脑的时候看到的配置24G1T里的1T就是硬盘&#xff0c;计算机…

ECharts 词云案例三:2024年阅读关键词

ECharts 词云案例三&#xff1a;2024年阅读关键词 引言 在数据可视化领域&#xff0c;ECharts 以其强大的功能性和灵活性&#xff0c;成为开发者和设计师的首选工具之一。继上一篇关于 ECharts 词云图的详细介绍后&#xff0c;本文将探索词云图的进阶应用——使用蒙版来创造更…