操作系统—经典同步问题
补充
互斥信号量mutex初值均为1
同步信号量根据问题实际描述自己设计
生产者-消费者问题
问题描述:一组生产者进程和一组消费者进程 共享一个初始为空、大小为n的缓冲区。(缓冲区:临界资源)
- 只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待
- 只有缓冲区不空时,消费者才能从中取出消息,否则必须等待
- 信号量mutex:互斥信号量,用于控制互斥访问缓冲池,初值为1
- 信号量full:同步信号量,用于记录当前缓冲池中的“满”缓冲区数,初值为0
- 信号量empty:同步信号量,用于记录当前缓冲池中的“空”缓冲区数,初值为n
注:①实现互斥的P操作一定要在实现同步的P操作之后
②两个V操作顺序可以交换
semaphore mutex=1; //临界区互斥信号量
semaphore empty=n; //同步信号量,表示空闲缓冲区数量
semaphore full=0; //同步信号量,缓冲区初始化为空,表示满缓冲区数量
producer(){ //生产者进程while(1){produce an item in nextp; //生产数据P(empty); //获取空缓冲区单元,消耗一个空闲缓冲区P(mutex); //进入临界区add nextp to buffer; //将数据放入缓冲区V(mutex); //离开临界区,释放互斥信号量V(full); //满缓冲区数+1,即增加一个产品}
}
//V(full)和P(full):实现两进程的同步关系,是在其中一个进程执行P,另一个进程执行V
consumer(){ //消费者进程while(1){P(full); //获取满缓冲区单元,消耗一个产品(非空缓冲区)P(mutex); //进入临界区remove an item from buffer; //从缓冲区中取出数据V(mutex); //离开临界区,释放互斥信号量V(empty); //空缓冲区数+1,即增加一个空闲缓冲区consume the item; //消费数据}
}
多生产者-多消费者
问题分析:桌上有一个盘子,每次只能向其中放入一个水果。
- 只有盘子为空时,爸爸或妈妈才可向盘子中放一个水果
- 仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出
如图,儿子和女儿之间没有互斥和同步关系。

- 信号量plate:互斥信号量,表示是否允许向盘子放入水果,初值为1(表示允许放入,且只允许放入一个)
- 信号量apple:同步信号量,表示盘子中是否有苹果,初值为0(表示盘子为空,不许取,apple=1可取)
- 信号量orange:同步信号量,表示盘子中是否有橘子,初值为0(表示盘子为空,不许取,apple=1可取)
注:在缓冲区大小=1的情况下,可以不设置mutex。但若缓冲区大小>1,则需要设置mutex
semaphore plate=1,apple=0,orange=0;
dad(){ //父亲进程while(1){prepare an apple; P(plate); //互斥向盘中取、放水果,相当于盘子数-1put the apple on the plate; //向盘中放苹果V(apple); //允许取苹果,相当于苹果数+1}
}
mom(){ //母亲进程while(1){prepare an orange;P(plate);put the orange on the plate;V(orange);}
}
son(){ //儿子进程while(1){P(orange); //互斥向盘中取橘子,相当于盘中橘子数-1take an orange from the plate;V(plate); //允许向盘中取、放水果,相当于盘子数+1,告诉父母盘子空了eat the orange;}
}
daughter(){ //女儿进程while(1){P(apple);take an apple from the plate;V(plate);eat the apple;}
}
读者-写者问题
问题描述:有读者和写者两组并发进程,共享一个文件
- 允许多个读者同时对文件执行读操作
- 只允许一个写者往文件中写信息
- 任意一个写者在完成写操作前不允许其他读者或写者工作
- 写者执行写操作前,应让已有的读者和写者全部退出
- 信号量count:记录当前读者的数量,初值为0
- 互斥信号量mutex:保护更新count变量时的互斥
- 互斥信号量rw:保证读者和写者的互斥访问
读进程优先
int count=0; //用于记录当前的读者数量
semaphore mutex=1; //用于保护更新count变量时的互斥
semaphore rw=1; //用于保证读者和写者互斥的访问文件
writer(){ //写者进程while(1){P(rw); //互斥访问共享文件——加锁writing; //写入V(rw); //释放共享文件——解锁}
}
reader(){ //读者进程while(1){P(mutex); //互斥访问count变量if(count==0) //当第一个进程读共享文件时——加锁P(rw); //阻止写进程写count++; //读者计数器+1V(mutex); //释放互斥变量countreading; //读取P(mutex); //互斥访问count变量count--; //读者计数器-1if(count==0) //当最后一个进程读共享文件时——解锁V(rw); //允许写进程写V(mutex); //释放互斥变量count}
}
读进程优先会导致:写进程“饿死”
写进程优先
当有读进程正在读共享文件时,有写进程请求访问,这时应禁止后续读进程的请求,等到已在共享文件的读进程执行完毕,立即让写进程执行
- 增加一个信号量w:用于实现“写优先”,初值为1
int count=0; //用于记录当前的读者数量
semaphore mutex=1; //用于保护更新count变量时的互斥
semaphore rw=1; //用于保证读者和写者互斥的访问文件
semaphore w=1; //用于实现“写优先”
writer(){ //写者进程while(1){P(w); //在无写进程请求时进入P(rw); //互斥访问共享文件——加锁writing; //写入V(rw); //释放共享文件——解锁V(w); //恢复对共享文件的访问}
}
reader(){ //读者进程while(1){P(w); //在无写进程请求时进入P(mutex); //互斥访问count变量if(count==0) //当第一个进程读共享文件时——加锁P(rw); //阻止写进程写count++; //读者计数器+1V(mutex); //释放互斥变量countV(w); //恢复对共享文件的访问reading; //读取P(mutex); //互斥访问count变量count--; //读者计数器-1if(count==0) //当最后一个进程读共享文件时——解锁V(rw); //允许写进程写V(mutex); //释放互斥变量count}
}
哲学家进餐问题
问题描述:一张圆桌边上坐着5名哲学家,每两名哲学家之间的桌上摆一根筷子,两根筷子中间是一碗米饭。哲学家们只会思考和进餐。
注:若遇到一个进程需要同时持有多个临界资源的情况,应参考哲学家问题的思想
- 哲学家在思考时,并不影响他人
- 只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根拿起)
- 若筷子已在他人手上,则需要等待
- 饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐。进餐完毕后,放下筷子继续思考

- 互斥信号量数组chopstick[5]={1,1,1,1,1}:用于对5个筷子的互斥访问
- 哲学家 i 号,左边筷子编号为 i ,右边筷子编号为 (i+1)%5
制定规则:当一名哲学家左右两边的筷子都可用时,才允许他抓起筷子(并不保证都可用时拿起)
semaphore chopstick[5]={1,1,1,1,1}; //初始化信号量
semaphore mutex=1; //设置取筷子的信号量
Pi(){ //i号哲学家的进程do{P(mutex); //在取筷子前获得互斥量P(chopstick[i]); //取左边筷子P(chopstick[(i+1)%5]); //取右边筷子V(mutex); //释放取筷子的信号量eat; //进餐V(chopstick[i]); //放回左边筷子V(chopstick[(i+1)%5]); //放回右边筷子think; //思考}while(1);
}
//哲学家进餐模板
//定义大锁
semaphore lock=1;
//定义资源数int
//如 有a、b、c三类资源,分配有9、8、5个,则定义3个int变量:int a=9; int b=8; int c=5;
Process(){while(1){P(lock);if(所有资源都够){所有资源int值减少;取xxx资源;V(lock);break;}V(lock);}做进程该做的事; //用中文说明即可P(lock);归还所有资源,所有资源int值增加;V(lock);
}
吸烟者问题(生产多个产品的单生产者)
问题描述:一个系统有三个抽烟者进程和一个供应者进程。
- 抽烟者需要三种材料:烟草、纸和胶水
- 第一个抽烟者拥有烟草,第二个抽烟者拥有纸,第三个抽烟者拥有胶水
- 供应者无限提供三种材料,供应者每次将两种材料(组合)放到桌子上。
- 拥有剩下那种材料的抽烟者卷一根烟并抽掉,同时给供应者一个信号告诉已完成,此时供应者就会将另外两种材料放到桌上
- 供应者与三个抽烟者是同步关系;三个抽烟者对抽烟这个动作是互斥
- 信号量offer1,offer2,offer3分别表示两两组合(烟草和纸的组合、烟草和胶水的组合、纸和胶水的组合)
- 信号量finish:用于互斥进行抽烟动作
int num=0; //存储随机数
semaphore offer1=0; //定义信号量对应烟草和纸组合的资源
semaphore offer2=0;
semaphore offer3=0;
semaphore finish=0; //定义信号量表示抽烟是否完成
provider(){ //供应者while(1){num++;num=(num+1)%3;if(num==0)V(offer1); //提供烟草和纸else if(num==1)V(offer2); //提供烟草和胶水elseV(offer3); //提供纸和胶水任意两种材料放在桌子上;P(finish);}
}
smoker1(){ //拥有烟草者while(1){P(offer3); //检查是否为组合3拿纸和胶水,卷成烟,抽掉;V(finish);}
}
smoker2(){ //拥有纸者while(1){P(offer2);拿烟草和胶水,卷成烟,抽掉;V(finish);}
}
smoker3(){ //拥有胶水者while(1){P(offer1);拿烟草和纸,卷成烟,抽掉;V(finish);}
}
理发师叫号
问题描述:一位理发师、一把理发椅,n把顾客等待理发的椅子
- 无顾客,理发师在理发椅上睡觉
- 有顾客,顾客叫醒理发师
- 理发师正在理发时,有顾客,该顾客坐在空椅上,若无空椅,则离开
int num=0; //表示有几个顾客等待被服务
semaphore lock=1; //互斥访问num
semaphore rest=0; //同步信号量,让服务人员排队等待的队列
semaphore wait=0; //同步信号量,让顾客排队等待的队列
Server(){ Customer(){while(1){ P(lock);P(lock); if(num>等待人数上限){ //有些场景可能没有规定人数上限if(num>0){ V(lock);num--; 离开;叫号; }else{V(lock); num++;V(wait); //唤醒一个顾客 取号/排队;为顾客服务; V(lock);}else{ V(rest); //唤醒一个等待的服务人员V(lock); P(wait); //等待被服务P(rest); //服务人员休息 被服务;} }} }
}
相关文章:
操作系统—经典同步问题
补充 互斥信号量mutex初值均为1 同步信号量根据问题实际描述自己设计 生产者-消费者问题 问题描述:一组生产者进程和一组消费者进程 共享一个初始为空、大小为n的缓冲区。(缓冲区:临界资源) 只有缓冲区没满时,生产者…...
profinet工业通信协议网关:提升钢铁冶炼智能制造效率的利器
工业通信协议网关profinet转ethercat(稳联技术WL-PN-ECATM)在钢铁冶炼生产线中的智能应用实践 在现代钢铁冶炼生产中,复杂的设备互联和数据传输对生产效率和质量控制至关重要。本案例详细阐述了某大型钢铁集团通过工业通信协议网关实现生产线…...
Vue基础:计算属性(描述依赖响应式状态的复杂逻辑)
文章目录 引言computed() 方法期望接收一个 getter 函数可写计算属性:计算属性的 Setter计算属性的缓存机制调试 Computed引言 推荐使用计算属性来描述依赖响应式状态的复杂逻辑 computed 函数:它接受 getter 函数并为 getter 返回的值返回一个不可变的响应式 ref 对象。 c…...
leetcode:1534. 统计好三元组(python3解法)
难度:简单 给你一个整数数组 arr ,以及 a、b 、c 三个整数。请你统计其中好三元组的数量。 如果三元组 (arr[i], arr[j], arr[k]) 满足下列全部条件,则认为它是一个 好三元组 。 0 < i < j < k < arr.length|arr[i] - arr[j]| &l…...
BUU27 [SUCTF 2019]CheckIn1
题目是上传文件 直接上传muma.jpg还不成功: 好吧,那做一个图片马上去,换马以后发现还是不行,呃啊啊啊啊 干啥啥不行,搜wp第一名,哎 新面孔:exif_imagetype 函数在 PHP 中用于检测一个文件是否为…...
unity学习30:Audio Source, Audio clip 音效和音乐
目录 1 音乐相关必须要有 Audio listener 和Source 2 Scene里必须要有 Audio listener 3 Audio Source 3.1 Audio Source 就是音源,可播放的音乐clip 分类 3.2 创建Audio Source 3.3 各种属性 3.4 3D sound Settings 4 使用脚本来播放声音 4.1 声明AudioC…...
【Qt 常用控件】输入类控件1(QLineEdit和QTextEdit 输入框)
目录 1.QLineEdit 单行输入框 例:输入个人信息,通过按钮提交 例:为输入框设置验证器,检查输入的电话 例:验证两次输入的密码是否一致 例:是否显示密码按钮,toggled信号。 2.QTextEdit多行输入框 、QPl…...
openEuler22.03LTS系统升级docker至26.1.4以支持启用ip6tables功能
本文记录了openEuler22.03LTS将docker升级由18.09.0升级至26.1.4的过程(当前docker最新版本为27.5.1,生产环境为保障稳定性,选择升级到上一个大版本26的最新小版本)。 一、现有环境 1、系统版本 [rootlocalhost opt]# cat /etc…...
深入解析:如何利用 Java 爬虫按关键字搜索淘宝商品
在电商领域,通过关键字搜索商品是常见的需求。无论是商家分析竞争对手,还是消费者寻找心仪的商品,获取搜索结果中的商品信息都至关重要。本文将详细介绍如何利用 Java 爬虫按关键字搜索淘宝商品,并提供完整的代码示例。 一、Java…...
STM32上部署AI的两个实用软件——Nanoedge AI Studio和STM32Cube AI
1 引言 STM32 微控制器在嵌入式领域应用广泛,因为它性能不错、功耗低,还有丰富的外设,像工业控制、智能家居、物联网这些场景都能看到它的身影。与此同时,人工智能技术发展迅速,也逐渐融入各个行业。 把 AI 部署到 STM…...
C++ Primer 成员访问运算符
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
芯科科技的BG22L和BG24L带来应用优化的超低功耗蓝牙®连接
全新的BG22L为常见蓝牙设备提供强大的安全性和处理能力,而BG24L支持先进的AI/ML加速和信道探测功能 2025年2月6日 – 致力于以安全、智能无线连接技术,建立更互联世界的全球领导厂商Silicon Labs(亦称“芯科科技”,NASDAQ&#x…...
java后端开发面试常问
面试常问问题 1 spring相关 (1)Transactional失效的场景 <1> Transactional注解默认只会回滚运行时异常(RuntimeException),如果方法中抛出了其他异常,则事务不会回滚(数据库数据仍然插…...
双非硕士的抉择:自学嵌入式硬件开发还是深入Linux C/C++走软开?
今天给大家分享的是一位粉丝的提问,双非硕研一是自学嵌入式走偏硬件还是说深入学习Linuxc/c走软开呢? 接下来把粉丝的具体提问和我的回复分享给大家,希望也能给一些类似情况的小伙伴一些启发和帮助。 粉丝提问: 老师好ÿ…...
Windows系统使用Git教程详解
使用 Git 可以帮助开发人员更好地进行版本控制和团队协作,下面是 Windows 上 Git 的详细使用教程。 安装 Git 首先,你需要在 Windows 上安装 Git。你可以从 Git 官网下载最新的安装包(https://git-scm.com/downloads),…...
Linux firewalld开启日志审计功能(2)
在Firewalld防火墙中启用和配置logdenied选项,记录被拒绝的数据包(等同于开启日志功能) 效果展示: 1.开启日志记录功能 firewall-cmd --set-log-deniedunicast #重新加载生效配置 firewall-cmd --reload 2.配置rsyslog捕获日志…...
【声音转文字CapsWriter】声音随时转化为文字,CapsWriter提高工作效率
文章目录 前言1. 软件与模型下载2. 本地使用测试3. 异地远程使用3.1 内网穿透工具下载安装3.2 配置公网地址3.3 修改config文件3.4 异地远程访问服务端 4. 配置固定公网地址4.1 修改config文件 5. 固定tcp公网地址远程访问服务端 前言 今天我要给大家安利一个神器——CapsWrit…...
深入理解小波变换:信号处理的强大工具
引言 在科学与工程领域,信号处理一直是关键环节,傅里叶变换与小波变换作为重要的分析工具,在其中发挥着重要作用。本文将深入探讨小波变换,阐述其原理、优势以及与傅里叶变换的对比,并通过具体案例展示其应用价值。 一…...
人机交互系统实验三 多通道用户界面
实验目的和要求 1)了解常见的多通道用户界面 2)查找资料,熟悉一种多通道用户界面并写出综述 实验环境 Windows10 实验内容与过程 (一) 实验内容: 要求上网查找资料,熟悉一种多通道用户界面并写出综述,可以是眼动跟踪、手势识别、 三维…...
Filter -> MaskFilter遮罩滤镜详解
MaskFilter 作用对象:MaskFilter 主要用于Paint的外观效果,给用Paint绘制的内容添加模糊或者浮雕效果应用效果: MaskFilter 处理位图的遮罩效果,影响绘制的边缘或整体形状主要用于模糊处理、浮雕效果等,通过影响绘制对…...
YOLOv10镜像作品集:高清图像目标检测惊艳案例分享
YOLOv10镜像作品集:高清图像目标检测惊艳案例分享 1. 引言:YOLOv10带来的视觉革命 在计算机视觉领域,目标检测技术正经历着前所未有的变革。YOLOv10作为最新一代的目标检测模型,以其无与伦比的速度和精度重新定义了实时检测的标…...
Kafka消费者组避坑指南:从位移提交到重平衡的实战经验
Kafka消费者组实战避坑指南:从位移管理到重平衡优化 在分布式消息系统中,Kafka消费者组的稳定性直接决定了数据处理的可靠性。我曾亲眼见证过一个电商大促场景下,由于消费者组配置不当导致百万级订单积压的故障。本文将分享七个关键场景的深度…...
不会画画也能创作!梦幻动漫魔法工坊新手入门全攻略
不会画画也能创作!梦幻动漫魔法工坊新手入门全攻略 1. 为什么你需要这个工具 你是否曾经有过这样的经历:脑海中浮现出一个绝妙的动漫角色形象,却因为不会画画而无法将它呈现出来?或者想为社交媒体创作独特的二次元头像ÿ…...
Axure 9.0 原生组件:绘制折线图
引言在原型设计中,数据可视化是传递核心信息的关键手段,而折线图凭借 “清晰展示数据趋势” 的优势,广泛应用于销售波动、用户增长、指标变化等场景。Axure 9.0 作为主流原型工具,虽未内置现成折线图组件,但通过「形状…...
金仓数据库KingbaseES KSQL命令行工具实战指南:从基础操作到高级调优
1. KSQL命令行工具入门指南 第一次接触金仓数据库的KSQL命令行工具时,我完全被它强大的功能震撼到了。作为DBA日常运维的瑞士军刀,KSQL不仅能完成基本的数据库操作,还能进行深度性能分析和调优。记得刚开始使用时,我还在纠结要不要…...
ViT在语义分割中的性能优化:从VOC2012数据集看如何提升自行车识别准确率
ViT在语义分割中的性能优化:从VOC2012数据集看如何提升自行车识别准确率 语义分割作为计算机视觉领域的核心任务之一,其目标是为图像中的每个像素分配类别标签。近年来,Vision Transformer(ViT)凭借其强大的全局建模能…...
用战神引擎开服后,别忘了这几步:服务器安全、日志监控与性能调优指南
战神引擎开服后的高阶运维指南:安全加固、日志监控与性能调优实战 当你成功用战神引擎架设传奇手游服务器后,真正的挑战才刚刚开始。服务器能跑起来只是第一步,如何让它跑得稳、跑得安全、跑得高效,才是区分普通服主和专业运维的关…...
springboot+vue基于web的在线学习资源推荐的设计与实现
目录功能模块分析推荐系统功能交互功能设计后台管理功能技术实现要点项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作功能模块分析 用户管理模块 用户注册与登录:支持邮箱/手机号注册,提供密码找回功能…...
Vision Master OpenCV 2.0 深度评测:新增YOLOv5、语义分割等ONNX模型,实战性能提升有多大?
Vision Master OpenCV 2.0 深度评测:ONNX模型实战性能全解析 当计算机视觉开发工具开始拥抱ONNX生态,技术选型的边界正在被重新定义。Vision Master OpenCV 2.0的发布恰逢其时,它不仅将YOLOv5、语义分割等前沿模型集成到可视化流程中…...
ClawdBot惊艳效果案例:PaddleOCR识别模糊手写体+LibreTranslate精准输出
ClawdBot惊艳效果案例:PaddleOCR识别模糊手写体LibreTranslate精准输出 1. 项目概述 ClawdBot是一个可以在个人设备上运行的AI助手应用,它使用vllm提供后端模型能力,为用户提供强大的多模态处理功能。这个应用特别适合需要处理文字识别和翻…...
