Linux学习日记23:信号量

一、前言

信号量是 Linux 中用于进程间、线程间同步与互斥的核心机制,其本质是一个计数器,通过原子操作(P/V 操作)控制并发实体对共享资源的访问权限。与互斥锁相比,信号量不仅支持 “独占式访问”(二值信号量),还能实现 “共享式访问”(计数信号量),适用场景更灵活。

二、信号量

2.1、信号量的定义

信号量是一个受保护的变量(或数据结构),仅支持三种原子操作:

初始化:设置信号量的初始值(对应可用资源数量)。

P 操作:申请资源。信号量值减 1,若结果小于 0,则当前进程、线程阻塞,直到有其他实体释放资源。

V 操作:释放资源。信号量值加 1,若结果大于等于 0,则唤醒一个阻塞的进程、线程。

用一句话来概括:信号量是一个“带计数器的同步原语”,用于控制多个线程、进程对共享资源的访问数量。举个例子就是,把信号量想成一个资源计数器,计数值 =当前可用资源数量,进程线程来用资源 →减 1,进程线程用完资源→加 1,计数为 0 →再来的人必须等待;信号量 = 计数 + 阻塞、唤醒机制。

2.2、信号量的特性

1、原子性:P/V 操作是不可中断的,避免并发修改导致的竞态条件。

2、阻塞性:当资源不可用时,申请方会主动阻塞,而非忙等。

3、灵活性:支持多资源并发访问(计数信号量)和独占访问(二值信号量)。

举个例子就是,如果现在有两个打印机,而现在同时有10份文件(线程)需要进行打印,在没有使用信号量的时候,10个文件同时打印,会超出打印机数量,会导致卡纸或者数据错乱,因为资源被非法利用了,本质是程序没有限制“同时能用资源的人数”;而使用了信号量以后,一个文件打印前,会进行申请(P操作),如果有就立刻用,如果没有就进行等,打印后,会释放资源(V操作),就是代表“我用完了,下面等待着的可以用了”。

2.3、POSIX 信号量

POSIX 信号量分为无名信号量有名信号量,前者适用于线程间或共享内存的进程间同步,后者适用于无共享内存的进程间同步。实际工程中最常用的是:POSIX 无名信号量,这里只讲POSIX 无名信号量。

2.3.1、初始化信号量:sem_init

函数原型如下:

#include <semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value);

参数:sem:指向要初始化的信号量对象(sem_t类型),需提前分配内存(全局、堆、共享内存);

pshared:信号量的作用域:0:仅用于线程间同步;1:用于进程间同步;

value:信号量初始值:1:二值信号量(等价互斥锁);>1:计数信号量(允许多个实体访问);0:用于同步(等待对方释放)。

返回值:成功:返回 0;失败:返回-1,并设置errno。

注:1、线程间使用时,sem必须是全局变量、静态变量或堆分配(不能是栈上的局部变量,否则线程无法访问);

2、进程间使用时,sem必须放在共享内存中;

3、同一个信号量只能初始化一次,重复初始化会导致未定义行为。

2.3.2、P操作:sem_wait

函数原型如下:

int sem_wait(sem_t *sem);

功能:原子性地将信号量值减 1:若减 1 后值 ≥ 0:成功获取资源,函数返回;若减 1 后值 < 0:当前线程、进程阻塞,直到有其他实体调用 sem_post 释放资源。

返回值:成功:返回 0失败:返回 -1,设置 errno。

注:阻塞是 “可中断的”:若线程被信号(如 SIGINT)中断, sem_wait会返回 -1 且 errno=EINTR,需手动处理(如重新调用)。

2.3.3、非阻塞 P 操作:sem_trywait

函数原型如下:

int sem_trywait(sem_t *sem);

功能:与 sem_wait 逻辑一致,但不阻塞:若能成功获取资源(信号量值 ≥ 1):值减 1,返回 0;若资源不可用(信号量值 = 0):立即返回 -1,errno=EINTR。

2.3.4、带超时的 P 操作:sem_timedwait

函数原型如下:

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

功能: 在 sem_wait 基础上增加超时机制:若超时前获取到资源:值减 1,返回0;若超时仍未获取资源:返回 -1,errno=ETIMEDOUT。

参数:abs_timeout:绝对时间(不是相对超时时间),结构体定义:

struct timespec { time_t tv_sec; // 秒 long tv_nsec; // 纳秒(0 ≤ tv_nsec < 1e9) };

如设置3秒超时:

struct timespec ts; // 获取当前时间 + 3 秒作为超时时间 clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 3; // 带超时申请资源 if (sem_timedwait(&sem, &ts) == -1) { if (errno == ETIMEDOUT) { printf("超时!3秒内未获取到资源\n"); } }

注:1、需链接 -lrt 库(编译时加 -lrt ),否则 clock_gettime 会报错;

2、超时时间是绝对时间,需基于当前系统时间计算,避免系统时间修改导致的异常。

2.3.5、V 操作:sem_post

函数原型如下:

int sem_post(sem_t *sem);

功能:原子性地将信号量值加 1:若加 1 后值 ≤ 0:说明有线程、进程因 sem_wait 阻塞,内核会唤醒其中一个阻塞的实体;若加 1 后值 > 0:无阻塞实体,仅更新信号量值。

返回值:成功:返回0;失败:返回 -1,设置 errno;

注:1、sem_post 是非阻塞的,调用后立即返回;

2、必须确保只有获取资源的实体调用 sem_post,否则会导致信号量值异常(如重复释放)。

2.3.6、获取信号量当前值:sem_getvalue

函数原型如下:

int sem_getvalue(sem_t *sem, int *sval);

功能:获取信号量的当前值,结果存入 sval 指向的变量:若信号量值 ≥ 0:*sval =信号量当前值。若有线程、进程阻塞在该信号量上:不同系统实现不同(Linux 下 *sval=-阻塞的实体数)。

返回值:成功:返回 0;失败:返回 -1,设置 errno;

示例如下:

int val; sem_getvalue(&sem, &val); printf("信号量当前值:%d\n", val);

2.3.7、销毁信号量:sem_destroy

函数原型如下:

int sem_destroy(sem_t *sem);

功能:销毁已初始化的无名信号量,释放其占用的资源。

返回值:成功:返回 0;失败:返回 -1,设置errno;

注:1、信号量销毁后,不能再调用其他操作(除非重新初始化);

2、进程退出前必须销毁已初始化的信号量,避免资源泄漏。

2.4、典型示例

使用信号量实现生产者,消费者模型,具体代码如下:

#include<stdio.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h> #include<semaphore.h> //creat sem sem_t produce_sem; sem_t customer_sem; typedef struct node { int data; struct node* next; }Node; //create head node Node* head = NULL; void* produce(void* arg) { while(1) { sem_wait(&produce_sem);//≥0进行生产 //create node Node* pnew = (Node*)malloc(sizeof(Node)); //init node pnew->data = rand()%1000; pnew->next = head; head = pnew; printf("produce: %ld,%d\n",pthread_self(),pnew->data); sem_post(&customer_sem);//customer++ sleep(rand()%3); } return NULL; } void* customer(void* arg) { while(1) { sem_wait(&customer_sem);//<0阻塞 //delete head node Node* pdel = head; head = head->next; printf("customer: %ld,%d\n",pthread_self(),pdel->data); free(pdel); sem_post(&produce_sem);//produce++ } return NULL; } int main() { //init sem sem_init(&produce_sem,0,4); sem_init(&customer_sem,0,0); //create p1,p2 pthread_t p1,p2; pthread_create(&p1,NULL,produce,NULL); pthread_create(&p2,NULL,customer,NULL); //p1,p2 join pthread_join(p1,NULL); pthread_join(p2,NULL); //kill sem sem_destroy(&produce_sem); sem_destroy(&customer_sem); return 0; }

编译并运行,结果如下:

可见,通过信号量进行控制,也可以实现生产者、消费者模型。

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

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

相关文章

深夜干货!6款大学生都在用的降ai率工具,教你如何免费降ai率,从此告别高AIGC预警!

你的论文是不是AI率超高&#xff1f;一查降ai率结果80%以上&#xff1f; 别急&#xff0c;这种情况很多人遇到过。 用AI工具写论文确实快&#xff0c;但“AI味”太浓就容易翻车。 今天我就来分享几款自己用过、真心能打的ai降ai工具&#xff0c;从免费降ai率工具到专业级都涵…

最近在车库折腾无感FOC方案时,发现STM32F030这颗白菜价MCU居然能跑滑模观测器。今天就把这套验证通过的方案拆开看看,老铁们可以直接拿去魔改

stm32f030无感foc方案&#xff0c;资料包括原理图&#xff0c;pcb&#xff0c;源程序&#xff0c;观测器参数&#xff0c;电流环参数计算表格。先看硬件部分&#xff08;原理图在附件FOC_V1.2.pdf&#xff09;。重点在电流采样电路设计&#xff0c;这里用了双电阻采样配运放INA…

最新降AIGC大汇总:免费盘点好用的降AI工具与降AI率干货,AIGC率从80%降到10%以下【建议收藏】

如果上天再给我一次机会&#xff0c;我绝对不会在答辩前一周才开始疯狂补论文&#xff0c;更不会天真地以为用AI辅助创作的的初稿能直接混过AI检测系统。 就在三天前&#xff0c;我看着查重报告上那个刺眼的“AIGC疑似度&#xff1a;88%”&#xff0c;整个人都麻了。导师在群里…

导师严选9个AI论文写作软件,专科生轻松搞定毕业论文!

导师严选9个AI论文写作软件&#xff0c;专科生轻松搞定毕业论文&#xff01; AI工具如何助你轻松应对论文写作难题 对于许多专科生而言&#xff0c;毕业论文写作不仅是学术能力的考验&#xff0c;更是一场时间与精力的挑战。尤其是在AIGC&#xff08;人工智能生成内容&#xff…

PDF工具类——实现PDF内容提取

一、引言&#xff1a;PDF文本提取的重要性 在现代软件开发中&#xff0c;PDF文件处理是一个常见需求。无论是从网络下载的PDF文档&#xff0c;还是用户上传的PDF文件&#xff0c;我们经常需要提取其中的文本内容进行进一步处理。例如&#xff1a;文档搜索、内容分析、信息归档…

强烈安利!专科生毕业论文必备的9个AI论文网站TOP9测评

强烈安利&#xff01;专科生毕业论文必备的9个AI论文网站TOP9测评 2026年专科生论文写作工具测评&#xff1a;如何选对AI平台提升效率 随着人工智能技术的不断进步&#xff0c;越来越多的专科生开始借助AI工具辅助毕业论文写作。然而&#xff0c;面对市场上琳琅满目的论文辅助网…

基于大数据的咖啡推荐平台的设计与实现

课题背景 随着互联网技术的发展和移动设备的普及&#xff0c;全球咖啡消费市场持续增长&#xff0c;消费者对个性化、精准化的咖啡推荐需求日益强烈。传统的咖啡推荐方式主要依赖人工经验或简单的用户调查&#xff0c;缺乏数据驱动的科学依据&#xff0c;难以满足现代消费者多样…

【开题答辩全过程】以 基于HTML5的移动端网页设计为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

别慌!2026年度学生论文降重工具实测:知网AIGC降AI率神器,避免通宵崩溃,三款十佳降AI产品全解析

为什么要用学生论文降重工具&#xff1f; 每当临近论文提交&#xff0c;特别是使用知网等权威检测系统时&#xff0c;我和许多同学都会因论文AI率过高而焦虑不安&#xff0c;生怕挂科。面对严格的AIGC检测&#xff0c;单靠人工修改往往费力又费时。一篇初稿经知网AI率检测达到…

【开题答辩全过程】以 基于Hadoop教育平台的设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

基于大数据的智慧旅游推荐与可视化平台

智慧旅游推荐与可视化平台的课题背景 随着全球旅游业的快速发展&#xff0c;游客对个性化、智能化的旅游服务需求日益增长。传统的旅游推荐系统往往依赖人工经验或简单的规则匹配&#xff0c;难以应对海量数据和复杂用户需求的挑战。大数据技术的兴起为旅游行业提供了新的解决方…

java map遍历方式,零基础入门到精通,收藏这篇就够了

一、Map集合遍历日常开发最常使用&#xff0c;简单总结五种方法差异。 ①、IteratorentrySet写法【推荐JDK8以下】&#xff0c;Map.Entry是Map接口的内部接口&#xff0c;获取迭代器&#xff0c;然后依次取出每个迭代器里面的Map.EntryIterator<Map.Entry<Integer,String…

2026年崩溃救命指南:知网AIGC检测通不过?这3款论文重复率降低神器帮你迅速降AI率,不再通宵抢修挂科!

论文重复率降低痛点分析与现实困境 作为一名研究生&#xff0c;论文查重挂科的压力几乎每天缠绕着我。尤其是在知网开启了越来越严格的AIGC检测后&#xff0c;之前通用的“简单改写”已经远远不够。我记得我最开始的论文初稿在知网AIGC检测中&#xff0c;AI率竟然高达62%&…

2026年知网AIGC检测通关必备论文改写降重十佳神器,告别通宵降AI率焦虑

论文改写降重的真实痛点&#xff1a;知网AI率高怎么办&#xff1f; 许多学生和研究者到了提交论文的最后阶段&#xff0c;才发现知网AIGC检测的论文AI率居高不下&#xff0c;焦虑到几乎通宵修改。AI率太高&#xff0c;过不了查重和降重门槛&#xff0c;直接挂科风险巨大。特别…

弱网条件下的阻抗小扰动稳定性分析:小信号模型、阻抗扫描与单逆变器SRF-PLL的时频域结果验证

弱网条件下基于阻抗小扰动稳定性分析&#xff0c;小信号模型&#xff0c;阻抗扫描&#xff08;电容电流反馈有源阻尼&#xff09;&#xff0c;单逆变器SRF-PLL&#xff0c;时域频域结果对应验证&#xff08;文档主要有奈奎斯特分析&#xff0c;simulink仿真结果&#xff0c;逆变…

2026年度崩溃救命指南:知网AIGC检测高分后,3款AI写作降重神器助你论文降AI率不过线

"#AI写作降重&#xff0c;知网AI率为什么越来越高&#xff1f; 每年毕业季临近&#xff0c;论文查重与AIGC检测成了学生最大的焦虑来源。特别是知网对AI生成内容检测越来越严格&#xff0c;不少同学初稿的论文AI率高达60%以上&#xff0c;严重威胁毕业进度。像我第一次用知…

50个JAVA常见代码大全:学完这篇从Java小白到架构师_java代码,收藏这篇就够了

50个JAVA常见代码大全&#xff1a;学完这篇从Java小白到架构师 Java&#xff0c;作为一门流行多年的编程语言&#xff0c;始终占据着软件开发领域的重要位置。无论是初学者还是经验丰富的程序员&#xff0c;掌握Java中常见的代码和概念都是至关重要的。本文将列出50个Java常用…

论文降重技巧2026:告别崩溃通宵,知网AIGC检测低于20%的降AI率秘诀揭秘!

"# 为什么论文AI率高成了学生的噩梦&#xff1f; 大学生在论文写作过程中&#xff0c;最怕的就是知网AIGC检测一出分数&#xff0c;AI率飙升到60%以上&#xff0c;担心挂科、毕业难题随之而来。尤其是随着AIGC的兴起&#xff0c;论文AI率检测门槛更高&#xff0c;简单改写…

论文AI率高到崩溃?选对论文降重平台,知网降AI率不再难

"# 写论文时&#xff0c;最怕遇到知网AIGC检测爆出超高论文AI率&#xff0c;那种通宵修改、怕挂科的焦虑让人崩溃不已。我自己刚开始写硕士论文时&#xff0c;初稿在知网检测出来的AI率高达62%。无奈之下&#xff0c;开始寻找靠谱的论文降重平台试用&#xff0c;最后找到两…

西门子S7-200组态王智能照明系统设计与研究:基于PLC与组态技术的公共楼道照明控制

西门子S7-200组态王基于PLC与组态的公共楼道智能照明系统的设计与研究 要 I ABSTRACT I 1 绪 论 1 1.1系统研究的背景及意义 1 1.1.1 背景 1 1.1.2 意义 1 1.2国内外研究现状 2 1.3 主要技术路线 2 2 系统需求分析及可行性分析 3 2.1需求分析 3 2.2总体设计 3 3 硬件设计 5 3.1…