《Linux从练气到飞升》No.30 深入理解 POSIX 信号量与生产消费模型

news2025/1/13 13:21:56

🕺作者: 主页

我的专栏
C语言从0到1
探秘C++
数据结构从0到1
探秘Linux
菜鸟刷题集

😘欢迎关注:👍点赞🙌收藏✍️留言

🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢阅读!!!

文章目录

    • 前言
    • 1 POSIX信号量相关概念
    • 2 POSIX信号量相关函数
    • 3 基于环形队列的生产消费模型

前言

在多线程编程领域,理解 POSIX 信号量的概念和相关函数是至关重要的。POSIX 信号量作为一种重要的同步原语,可以帮助我们在多线程环境中实现线程之间的协调与同步,从而确保数据的一致性和避免竞争条件的发生。

本篇博客旨在深入探讨 POSIX 信号量的基本概念和相关函数,帮助读者全面理解这一关键的并发编程工具。通过本文的学习,读者将能够掌握如何灵活地运用 POSIX 信号量来构建并发程序,提高程序的性能和可靠性。让我们一起深入探索 POSIX 信号量的奥秘,为多线程编程的世界增添新的智慧与力量。

1 POSIX信号量相关概念

POSIX信号量是什么?

信号量的本质是一个计数器,是用来描述临界资源有效的计数器

POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。
当多个线程想要获取信号量的时候,都会对信号量当中的资源计数器进行减一操作。
如果初始化信号量的资源计数器的值为1表示当前只有一个资源,这就意味着只有一个线程在同一时刻可以获取到信号量。
如果想要实现线程同步,初始化信号量的资源计数器的值就不必为1了,它可以根据需要设置

  • 如果大于0则表示还有多少资源可以使用
  • 等于0则表示没有资源可以使用
  • 小于0则表示有多少线程在等待资源。

2 POSIX信号量相关函数

  1. 信号量初始化
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
	sem_t: 信号量的类型
	sem: 传入待要初始化的信号量
	pshared: 0 表示线程间共享,非0表示进程间共享
	value:信号量初始值
  1. 信号量销毁
int sem_destroy(sem_t *sem);
参数:
	sem:待销毁的信号量
  1. 信号量等待
功能:等待信号量,会将信号量的值减1
	int sem_wait(sem_t *sem); //P()
  1. 信号量发布
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1int sem_post(sem_t *sem);//V()

3 基于环形队列的生产消费模型

  • 上一个生产者-消费者的例子是基于queue的,其空间可以动态分配,现在基于固定大小的环形队列重写这个程序(POSIX信号量)。

image.png

  • 环形结构起始状态和结束状态都是一样的,不好判断为空或者为满,所以可以通过加计数器或者标记位来判断满或者空。另外也可以预留一个空的位置,作为满的状态

image.png
但是我们现在有信号量这个计数器,就很简单的进行多线程间的同步过程
实现代码如下:
RingQueue.cc

#pragma

#include<iostream>
#include<unistd.h>
#include<vector>
#include<semaphore.h>
#include<stdlib.h>

#define NUM 10

class RingQueue
{
private:
    std::vector<int> v;
    int _cap;//容量
    sem_t sem_product;//生产者
    sem_t sem_consume;//消费者

    int p_index;//生产者索引
    int c_index;//消费者索引

public:
    RingQueue(int cap=NUM)
        :_cap(cap),v(cap)
    {
        sem_init(&sem_product,0,cap);
        sem_init(&sem_consume,0,0);
        p_index = 0;
        c_index = 0;
    }
    ~RingQueue(){
        sem_destroy(&sem_product);
        sem_destroy(&sem_consume);
    }

    void put(const int&in){
        sem_wait(&sem_product);
        v[p_index] = in;
        p_index++;
        p_index = p_index%NUM;
        sem_post(&sem_consume);
    }

    void get(int &out){
        sem_wait(&sem_consume);
        out = v[c_index];
        c_index++;
        c_index = c_index%NUM;
        sem_post(&sem_product);
    }
};

main.cc

#include"RingQueue.cc"
using namespace std;

void* Consumer(void* arg){
    RingQueue *bq = (RingQueue*)arg;
    int data;
    while(1){
        bq->get(data);
        cout<<"I am "<<pthread_self()<<" is consumer : "<<data<<endl;
    }
}

void* Product(void* arg){
    RingQueue* bq = (RingQueue*)arg;
    srand((unsigned int)time(NULL));
    while(1){
        int data = rand()%100;
        bq->put(data);
        cout<<"I am "<<pthread_self()<<" is product "<<data<<endl;
        sleep(1);
    }
}


int main()
{
    RingQueue* pq = new RingQueue();
    pthread_t c;
    pthread_t p;
    pthread_create(&c,NULL,Consumer,(void*)pq);
    pthread_create(&p,NULL,Product,(void*)pq);

    pthread_join(c,NULL);
    pthread_join(p,NULL);
    return 0;
}

makefile

main:main.cc
	g++ -o $@ $^ -lpthread
.PHONY:
clean:
	rm -f main

结果:
可以观察到生产一个消费一个
image.png

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

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

相关文章

vs2017 编译Qt 5.11.2 源码

SDK 10.0.22000.194 有 2种编译方式 &#xff0c;第二种 看下面 推荐使用方式二&#xff0c;简单方便&#xff0c;唯一不好是慢 方式一: 1、问题描述&#xff1a; 使用VS编译程序时&#xff0c;运行库选择多线程&#xff08;/MT&#xff09;&#xff0c;表示采用多线程静态…

安卓用户当心: CERT-IN 发布高危漏洞警告

已发现的漏洞一旦被利用&#xff0c;将构成严重风险&#xff0c;可能导致未经授权访问敏感信息。 印度计算机应急响应小组&#xff08;CERT-IN&#xff09;在最近发布的一份公告中&#xff0c;就影响印度安卓用户的新安卓漏洞发出了重要警告。 该警告对使用安卓 11、12、12L、…

modbus转profinet网关连接PLC与变频器控制摆辊应用在涂布机案例

通过兴达易控modbus转profinet网关的应用&#xff0c;PLC能够直接与变频器进行通讯&#xff0c;并实现对摆辊的精确控制。兴达易控modbus转profinet网关&#xff08;XD-MDPN100&#xff09;作为一个高性能的转换设备&#xff0c;能够稳定可靠地完成modbus和profinet之间的数据转…

2023最新最全【Python3.11.3】下载安装零基础教程【附安装包】

前言&#xff1a;链接在最底下 Python是一种可在多个平台上运行的计算机程序设计语言&#xff0c;它是一种高层次的脚本语言&#xff0c;结合了解释性、编译性、互动性和面向对象的特点。最初&#xff0c;它的设计目的是用于编写自动化脚本(shell)。但随着版本的更新和新功能的…

vue 城市选择器的使用 element-china-area-data

一、Element UI 中国省市区级联数据 本文参考&#xff1a;element-china-area-data - npm 1. 安装 npm install element-china-area-data -S2. 使用 import { provinceAndCityData, regionData, provinceAndCityDataPlus, regionDataPlus, CodeToText, TextToCode } from e…

学习模拟简明教程【Learning to simulate】

深度神经网络是一项令人惊叹的技术。 有了足够的标记数据&#xff0c;他们可以学习为图像和声音等高维输入生成非常准确的分类器。 近年来&#xff0c;机器学习社区已经能够成功解决诸如对象分类、图像中对象检测和图像分割等问题。 上述声明中的加黑字体警告是有足够的标记数…

git 构建报错

钉钉插件]当前任务未配置机器人&#xff0c;已跳过 org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: WorkflowScript: 4: Tool type “maven” does not have an install of “maven-3.8.8” configured - did you mean “Maven-3.8.8”? …

Docker Desktop 配置阿里云镜像加速

阿里云搜索镜像&#xff0c;打开容器镜像服务&#xff0c;复制镜像加速器地址 Docker Desktop 右上角设置&#xff0c;选择 Docker Engine&#xff0c;在配置中添加阿里云的镜像地址&#xff0c;右下 Apply & restart 即可。 "registry-mirrors": ["https…

android适配鸿蒙系统开发

将一个Android应用迁移到鸿蒙系统需要进行细致的工作&#xff0c;因为两者之间存在一些根本性的差异&#xff0c;涉及到代码、架构、界面等多个方面的修改和适配。以下是迁移工作可能涉及的一些主要方面&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专…

《Linux从练气到飞升》No.29 生产者消费者模型

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

机械人必须要了解的丝杆螺母参数

丝杆螺母是机械中重要的零部件之一&#xff0c;主要用于将旋转运动转化为直线运动&#xff0c;或者将直线运动转化为旋转运动。只有正确了解丝杆螺母的参数&#xff0c;才能进行选型。 1、螺纹规格&#xff1a;丝杆螺母的螺纹规格是按照国家标准进行分类的&#xff0c;常见的有…

设置chunk自动扩展到多大

1. 设置chunk自动扩展 execute function task(modify chunk extendable on,8); 2. 设置dbs扩展到多大合适 execute function task(modify space sp sizes,testdb1024,1024,10240) testdb 初始1MB 下次扩1MB 最大10MB

leetcode算法之前缀和

目录 1.DP34[模板]一维前缀和2.DP35[模板]二维前缀和3.寻找数组的中心下标4.除自身以外数组的乘积5.和为K的子数组6.和可被K整除的子数组7.连续数组8.矩阵区域和 1.DP34[模板]一维前缀和 一维前缀和 #include <iostream> #include <vector> using namespace std…

《视觉SLAM十四讲》-- 后端 2

文章目录 09 后端 29.1 滑动窗口滤波和优化9.1.1 实际环境下的 BA 结构9.1.2 滑动窗口法 9.2 位姿图9.2.1 位姿图的意义9.2.2 位姿图优化 09 后端 2 9.1 滑动窗口滤波和优化 9.1.1 实际环境下的 BA 结构 由于计算机算力的限制&#xff0c;我们必须控制 BA 的规模&#xff0c…

【教3妹学编程-算法题】最大和查询

3妹&#xff1a;2哥&#xff0c;你有没有看到新闻“18岁父亲为4岁儿子落户现身亲子鉴定” 2哥 : 啥&#xff1f;18岁就当爹啦&#xff1f; 3妹&#xff1a;确切的说是14岁好吧。 2哥 : 哎&#xff0c;想我30了&#xff0c; 还是个单身狗。 3妹&#xff1a;别急啊&#xff0c; 2…

【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)

文章目录 先看本次实现的最终效果前言把敌人和炮塔全部配置成预制体炮塔商店打开商店放置炮塔升级炮塔出售显示炮塔攻击范围显示玩家金额和血量关闭升级面板和商店功能源码完结 先看本次实现的最终效果 前言 本期紧接着上一篇&#xff0c;本期主要内容是实现商店、购买、出售、…

js的File对象,Blob和file相互转换

示例 <!DOCTYPE html> <html><head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1" /><title>js的File对象&#xff0c;Blob和file相互转换</title><…

生成对抗网络Generative Adversarial Network,GAN

Basic Idea of GAN Generation&#xff08;生成器&#xff09;  Generation是一个neural network&#xff0c;它的输入是一个vector&#xff0c;它的输出是一个更高维的vector&#xff0c;以图片生成为例&#xff0c;输出就是一张图片&#xff0c;其中每个维度的值代表生…

中级程序员——uniapp和小程序面试题

&#x1f604;博主&#xff1a;小猫娃来啦 &#x1f604;文章核心&#xff1a;uniapp和小程序面试题 文章目录 用uniapp有遇到一些兼容性问题吗&#xff1f;uniapp最大的优点是什么&#xff1f;uniapp如何实现多端兼容&#xff1f;uniapp是如何做跨端适配的&#xff1f;常用的u…

lxml基本使用

lxml是python的一个解析库&#xff0c;支持HTML和XML的解析&#xff0c;支持XPath解析方式&#xff0c;而且解析效率非常高 XPath&#xff0c;全称XML Path Language&#xff0c;即XML路径语言&#xff0c;它是一门在XML文档中查找信息的语言&#xff0c;它最初是用来搜寻XML文…