Linux之posix信号量

【Linux】POSIX信号量 文章目录一. 什么是POSIX信号量?二. 为什么要有POSIX信号量?三. POSIX信号量实现原理四. POSIX信号量接口函数1. 创建、初始化信号量2. 销毁信号量3. 等待(申请)信号量4. 发布(释放)信号量五. 信号量的应用1. 二元信号量模拟互斥锁2. 基于环形队列的生产者消费者模型2.1 四个规则2.2 环形队列的实现2.3 单生产者单消费者2.4 多生产者多消费者 一. 什么是POSIX信号量? POSIX和System V都是可移植的操作系统接口标准,它们都定义了操作系统应该为应用程序 阅读详情

今天来讲下POSIX信号量,用于同步操作,达到无冲突的访问共享资源的目的,可以用于线程间同步。

信号量就是一个计数器+等待队列+等待+唤醒

1.信号量的基本接口

1)初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem:信号量变量
pshared:0表示线程间共享,非0表示进程间共享(决定用于线程间还是进程间)
value:信号量初始值

2)销毁信号量
int sem_destroy(sem_t *sem);

3)等待信号量
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);

4)发布信号量
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。 int sem_post(sem_t *sem);

信号量和条件变量的区别:
信号量与条件变量的区别:信号量拥有资源计数的功能,临界资源是否能够操作通过自身技术判断,条件变量是搭配互斥锁一起使用的,信号量还可以实现互斥,计数仅为0/1< font>

2.信号量实现生产者与消费者模型

上一节我用基本队列实现了一个生产者与消费者模型,这节我将用信号量和大小固定的环形
队列再次实现生产者与消费者模型:

实现代码

  1 #include<iostream>
  2 #include<pthread.h>
  3 #include<vector>
  4 #include<semaphore.h>
  5 
  6 //实现线程安全的环形队列,用信号量和线性表实现
  7 //信号量就是一个计数器,具有等待队列+等待+唤醒功能
  8 
  9 class RingQueue
 10 {
 11 public:
 12     RingQueue(int cap = 10):queue(10),capacity(cap)      //构造函数,采用了初始化列表的形式,定义环形队列大小capacity为10
 13             ,write_step(0),read_step(0){
 14         //int sem_init(sem_t *sem, int pshared, unsigned int value);
 15         //sem:信号量变量
 16         //pshared:决定信号量用于线程还是进程
 17         //0为线程   !0为进程
 18         //value:信号量初始计数
 19         sem_init(&data,0,0);
 20         sem_init(&idle,0,cap);
 21         sem_init(&lock,0,1);
 22     }
 23     ~RingQueue(){                         //析构函数
 24         sem_destroy(&data);
 25         sem_destroy(&idle);
 26         sem_destroy(&lock);
 27     }
 28     bool QueuePush(int data){
 29         ProductorWait();                  //因为信号量自带一个计数功能,所以不需要在循环判断,先加一个等待是为了判断是否队列空了,如果先加锁然后却发现满了程序就会卡在productorwait()那里没有解锁。
 30         QueueLock();                     //访问临界资源加锁
 31         queue[write_step] = data;        //放数据
 32         write_step = ((write_step)+1)%capacity;   //写指针要改变
 33         QueueUnlock();                   //访问完毕后解锁,因为锁只是限制临界资源的访问,不限制其他操作
 34         ConsumorWakeUp();                //唤醒消费者
 35         return true;
 36     }
 37     bool QueuePop(int *data){          
 38         ConsumorWait();      //同理先加一个等待是为了判断是否有资源可以取,否则先加锁了,结果发现没有临界资源可以访问,则会卡在consumorwait()那里没有解锁。
 39         QueueLock();
 40         *data = queue[read_step];               //取数据
 41         read_step = ((read_step)+1)%capacity;   //渎指针要改变
 42         QueueUnlock();
 43         ProductorWakeUp();
 44         return true;
 45     }
 46 private:
 47     void QueueLock(){
 48         sem_wait(&lock);
 49     }
 50     void QueueUnlock(){
 51         sem_post(&lock);
 52     }
 53     void ConsumorWait(){
 54         sem_wait(&data);
 55     }
 56     void ConsumorWakeUp(){
 57         sem_post(&data);
 58     }
 59     void ProductorWait(){
 60         sem_wait(&idle);
 61     }
 62     void ProductorWakeUp(){
 63         sem_post(&idle);
 64     }
 65 private:
 66     std::vector<int> queue;
 67     int capacity;
 68     int write_step;
 69     int read_step;
 70     sem_t data;   //代表消费者信号量    
 71     sem_t idle;   //代表生产者信号量
 72     sem_t lock;
 73 };
 74 
 75 void* pth_consumor(void* arg)
 76 {
 77     RingQueue *q = (RingQueue*) arg;
 78     while(1){
 79         int data;
 80         q->QueuePop(&data);
 81         std::cout<<"consumor get data!"<<std::endl;
 82     }
 83     return NULL;
 84 }
 85 
 86 void* pth_productor(void* arg)
 87 {
 88     RingQueue* q = (RingQueue*) arg;
 89     int i=0;
 90     while(1){
 91         q->QueuePush(i);
 92         std::cout<<"productor put data!"<<std::endl;
 93         i++;
 94     }
 95     return NULL;
 96 }
 97 
 98 int main()
 99 {
100     pthread_t ctid[4],ptid[4];
101     int ret,i;
102     RingQueue q;
103     for(i=0;i<4;i++){
104         ret = pthread_create(&ctid[i],NULL,pth_consumor,(void*)&q);
105         if(ret!=0){
106             std::cout<<"consumor not exist!"<<std::endl;
107             return -1;
108         }
109     }
110     for(i=0;i<4;i++){
111         ret = pthread_create(&ptid[i],NULL,pth_productor,(void*)&q);
112         if(ret!=0){
113             std::cout<<"productor not exist!"<<std::endl;
114             return -1;
115         }
116     }
117     for(i=0;i<4;i++){               //线程等待
118         pthread_join(ctid[i],NULL); 
119     }
120     for(i=0;i<4;i++){
121         pthread_join(ptid[i],NULL);
122     }
123     return 0;
124 }

Linux进程同步之POSIX信号量 POSIX信号量是属于POSIX标准系统接口定义的实时扩展部分。在SUS(Single UNIX Specification)单一规范中,定义的XSI IPC中也同样定义了人们通常称为System V信号量的系统接口。信号量作为进程间同步的工具是很常用的一种同步IPC类型。 在《UNIX网络编程 卷2:进程间通信》的前言第二页与第1版的区别中作者提到“POSIX IPC函数时大势所趋,因为他们比 阅读详情

相关推荐

nvprof:CUDA编程性能分析工具

NVIDIA提供了具有高性能计算的GPU产品,如何检验硬件的实际性能,写出高效的CUDA代码让算力加速卡物尽其用,那可以通过其配套提供的“护城河”软件工具链来检验和帮助发挥GPU的性能:nvprof。如下,对于将8192个A,B向量进行向量加法运算,即C[i] = A[i] + B[i],当软件设置不同的blocknum, threadnum时候,CUDA执行kernel的时间是不同的。比如如下命令,可以看到程序tmp1的总体性能,下面一行是打印gpu的执行时间情况。

Briwisdom的博客 3384

python:posix --- 最常见的 POSIX 系统调用

python:posix --- 最常见的 POSIX 系统调用

FuncPlotCalc 505

ios快捷指令进行钉钉打卡

首先 1、打开快捷指令 2、自动化 3、创建个人自动化-特定时间 4、添加操作-搜索“随机数” 5、最小值和最大值填充 6、添加操作-搜索“等待” 7、长按“1秒钟”,选择魔法变量,选择上一步的随机数 6、添加操作-搜索“钉钉” 7、选择钉钉-随便一个聊天窗口。 8、添加操作-搜索“等待”,这次将等待时间设为10秒 9、添加操作 “搜索天气” ,选择显示天气。 注意点: 1、此操作依赖于钉钉极速打卡,只是帮忙唤起钉钉。 2、保存自动化时有个运行前询问,务必关掉。 3、手机不能设

blaze_jack 5万+

【Linux】多线程 之 POSIX信号量

若临界资源只有1个,则sem设为1,当要使用临界资源时,sem由1变为0,其他人在想申请,则申请不到挂起排队,等待释放临界资源时 sem由0变为1 ,才可以再申请临界资源。POSIX信号量 和system V 信号量 作用相同,都是用于同步操作,达到无冲突的访问共享资源目的,但。当A和B开始,桌子上没有苹果时 ,或者 桌子上全都是苹果时,都会访问同一个盘子。有一个很大的桌子,存在像钟表的0-12点刻度的区域,在每个刻度中放入一个盘子。生产者生产数据在当前空间,则对应的数据+1,所以消费者可以拿数据。

qq_62939852的博客 1600

从零上手HiAgent:构建能听懂指令的智能体框架实战指南

智能体(Agent)作为人工智能领域的重要范式,正从传统的预设流程自动化转向以目标驱动的自主规划与执行。其核心原理在于利用大语言模型(LLM)作为决策大脑,通过任务规划、工具调用与记忆机制,将模糊的自然语言指令转化为可执行的工作流。这一技术显著提升了人机协作的效率和自然度,其价值在自动化办公、数据分析与智能流程编排等场景中尤为突出。本文聚焦于HiAgent这一具体框架,深入解析其作为智能体开发平台的核心架构,涵盖规划器、执行器、工具集等关键组件,并提供从环境配置、自定义工具开发到复杂任务链构建的完整工程实践

weixin_29266007的博客 889

【个人记录】CentOS7升级glibc至2.28

由于CentOS7系统已经停止支持, 虽然大部分业务已经迁移至OpenEuler,但仍然有部分业务系统跑在CentOS7上。在尝试部署新业务环境时经常会提示如下错误(以code-server运行需要的node 20为例)node -v为了保障业务可正常运行,通常采用Docker继承好的node环境进行部署,但部分场景还是需要宿主机使用新版glibc版本。本文记录本人一次成功升级glibc(2.17=>2.28)的步骤。

喵呜 3883

初识linux之POSIX信号量

本文介绍了POSIX信号量的概念和使用,以及通过POSIX信号量和循环队列实现了一个简单的多线程中的生产消费模型

Masquerena114514的博客 883

海康安防平台接口调试指南:从签名生成到Vue项目集成

本文详细解析了海康安防平台接口认证规则,从签名生成到Vue项目集成的完整流程。通过核心机制解析、签名工具使用技巧及Vue项目中的优雅集成方案,帮助开发者高效完成接口调试,避免常见问题。特别适合需要将海康安防平台接口集成到Vue项目中的开发者参考。

weixin_42533120的博客 438

【Linux】-- POSIX信号量

在没有信号量这个计数器的时候,因为不知道临界资源的状态,所以需要先加锁,再使用临界资源进行判断(条件变量),于是满了就释放锁并挂起。因为,就相当于如果我们先加锁,如此去申请信号量的线程一定是很少的,而这个程序的工作效率是高还是低,是取决于我们将这个资源如何快速的派发给线程。虽然,生产任务、拿任务,都是一个一个的做的,但是处理任务的时候,是可以变为并发的。信号量本质是一个计数器,只要申请成功了,其是对于临界资源的预定机制,只要预定成功就一定会有对应的资源。所以,对于此的解决方式,是势必要使用加锁的。

weixin_64609308的博客 654

Windows C语言编程:Beep API实现蜂鸣器原理与实战

如果你在 Windows 上写过 C 语言程序,想给程序加个简单的提示音,第一个想到的可能是 printf("\a") 。这个转义字符确实能在某些终端里发出“嘀”的一声,但它太原始、太不可控了,而且很多时候根本没声音。那么,有没有一种更“Windows”、更可控、更专业的方法来让你的程序“说话”呢? 答案是肯定的,而且它比你想象的要强大和复杂。Windows 提供了一个名为 Beep 的 API 函数,专门用于生成蜂鸣声。你可能觉得这功能太简单,甚至有点过时——不就是让电脑“哔”一声吗?但恰恰是这个看似简单

weixin_34109408的博客 395

【25届数字IC秋招总结】面试经验10——紫光同芯

25届数字ic面试记录——紫光同芯

lalala0635的博客 862

Linux线程——线程互斥、同步、POSIX信号量

本文探讨了线程互斥与同步的概念及其实现方法。文章首先通过模拟抢票程序展示了多线程访问共享资源时可能出现的数据不一致问题,如票数出现负值的情况。分析指出,这是由于共享资源访问未加保护导致的线程安全问题。 为解决这一问题,文章介绍了使用pthread库中的互斥量(mutex)来保护共享资源。通过加锁机制,确保同一时间只有一个线程能访问关键代码段,从而避免了数据竞争。文章详细解析了ticket自减操作的汇编实现,结合操作系统分时调度的特点,解释了数据不一致的根本原因。 此外,文章还简要提及POSIX信号量的使用,

2301_79705195的博客 1447

【大模型学习】第二十四章 生成式人工智能(GAI)简介

‌的AI技术,其核心目标是通过学习数据中的规律,生成与训练数据类似但全新的文本、图像、音频、视频甚至代码。生成式人工智能(GAI)是一类能够‌。

以实战经验介绍行业知识 1637

linux下的posix信号量

linux下的posix信号量

2302_80190394的博客 1051

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【Linux】线程POSIX信号量

本文介绍了信号量的概念及其在多线程编程中的应用。信号量主要用于同步操作,确保无冲突地访问共享资源。POSIX信号量可用于线程间同步,本质是一个计数器,用于预定特定资源。文章详细说明了信号量的基本接口,包括初始化、P操作(申请资源)、V操作(释放资源)和销毁信号量。此外,文章还通过生产者消费者模型的实例,展示了如何利用信号量和互斥锁实现线程间的同步与互斥,特别是在多生产者多消费者场景中,如何通过信号量筛选有效线程,避免死锁,并保证操作的原子性。最后,文章提供了一个基于环形队列的生产者消费者模型的代码实现。

2301_81577798的博客 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Linux POSIX 信号量 命名信号量与未命名信号量

Linux POSIX 信号量 命名信号量与未命名信号量 文章目录Linux POSIX 信号量 命名信号量与未命名信号量命名信号量的创建初始化一个未命名信号量发布信号量和等待信号量获取信号量的当前值关闭一个命名信号量删除一个命名信号量销毁一个未命名信号量 注意: 1、Linux信号量是一个递加递减的正整数,而不是ON、OFF的bool量。 2、Linux信号量数值为0时,尝试去递减该信号量,则会...

huwei039的博客 1903

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【Linux】POSIX信号量{基于环形队列的PC模型/理解信号量的出现/参考代码}

POSIX信号量{基于环形队列的PC模型/理解信号量的出现/参考代码}

Ape's IT Blog 1256

【Linux】多线程6——POSIX信号量,环形队列cp问题

此时由于生产者生产的很快,运行代码后一瞬间生产者就将环形队列打满了,此时生产者想要再进行生产,但空间资源已经为0了,于是生产者只能在blank_sem的等待队列下进行阻塞等待,直到由消费者消费完一个数据后对blank_sem进行了V操作,生产者才会被唤醒进而继续进行生产。虽然消费者消费的很快,但一开始环形队列当中的数据资源为0,因此消费者只能在data_sem的等待队列下进行阻塞等待,直到生产者生产完一个数据后对data_sem进行了V操作,消费者才会被唤醒进而进行消费。

2301_80224556的博客 2339

linux信号量POSIX,linux Posix 信号量 三 (经典例子)

本文将阐述一下信号量的作用及经典例子,当中包括“《越狱》寄信”,“家庭吃水果”,“五子棋”,“接力赛跑”,“读者写者”,“四方恋爱”等首先,讲semWait操作(P操作)和semSignal操作(V操作)的一些基本原则。(接下来同意称为P,V操作)1. P操作,s - -,if(s<0)阻塞自己2. V操作,s++,if(s<=0)唤醒一个其他进程3. P,V操作时原语(通俗讲,就是...

weixin_42323034的博客 427

Linux系统编程系列之POSIX信号量

Linux系统编程系列之POSIX信号量,POSIX信号量的简单介绍和使用

AABond的博客 432

Linux系统之----POSIX信号量

信号量是一个非负整数,用于控制对共享资源的访问。它的值表示可用资源的数量。:将信号量的值减1。如果信号量的值小于0,则进程,等待信号量的值变为非负。:将信号量的值加1。如果信号量的值大于0,则一个等待该信号量的进程。

2401_85878549的博客 1186

Linux多进程通信(2)——POSIX信号量使用例程

1),而POSIX信号量分为有名信号量和无名信号量,而System V标准的信号量并不是,Posix通过sem_open单一的调用就完成了信号量的创建、初始化和权限的设置,而System V要两步。POSIX无名信号量,POSIX信号量,用能看到,而System V信号量,则是使用查看。:可以在多进程间使用,多进程通过名字来打开同一个信号量,使用范围更广:一般在多线程使用,因为没有名字,所以没法在多进程中打开同一个信号量。

嵌入式Linux开发从业者,立志做一名优秀的博客输出者! 1094

Linux IPC:POSIX 信号量

有名信号量 (Named Semaphores):可以在多个进程之间共享。无名信号量 (Unnamed Semaphores):仅限于在同一进程内的线程之间共享。

极客代码 1121

linux进程线程同步之 - POSIX无名信号量

无名信号量(匿名信号量) 使用范围:线程间同步,相关进程间同步 一、函数介绍 1.初始化无名信号量 #include int sem_init(sem_t *sem, int pshared, unsigned int value); 函数功能:sem_init() 初始化一个定位在 sem 的匿名信号量。 返回值:sem_init() 成功时返回 0;错误时,返回 -1,并把

1171
上一篇: Linux之生产者与消费者模型
下一篇: C++ 模板
Python_programer
博客等级 码龄9年 25粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值