信号量机制以及各种例题
信号量机制
1.整型信号量
整型信号量定义为一个用于表示资源数目的整型量,除了初始化外,只能由wait(S)和signal(S)这两个操作访问。wait又称为P操作,signal又称为V操作。
wait(S){while(S<=0); /*do no-op*/S--;
}
signal(S){S++;
}
在wait操作中,当S<=0,表示资源数目不够,这时就会一直在while循环中,并什么都不做,使得进程处于“忙等”状态。
wait和signal可以理解为对资源数目的-1和+1,一次wait操作表明要使用一个资源,一次signal操作表明归还一个资源或者产生一个资源。
2.记录型信号量
记录型信号量可以解决上述的“忙等”问题,不会一直停留在wait操作中,但是会出现多个进程等待访问同一临界资源的情况。为此除了表示资源数目的整型变量为value,还增加了一个进程链表指针list,用于链接上述的所有等待进程。
记录型数据结构
typedef struct{int value;struct process_control_block *list;
}semaphore;
wait和signal操作
wait(semaphore *S){S->value--;if(S->value<0) block(S->list);
}
signal(semaphore *S){S->value++;if(S->value<=0) wakeup(S->list);
}
在wait操作中,先自减,如果资源数目小于0,说明资源不够用,这时就要把该进程从运行状态block为阻塞状态 ,进程需要等待,但是该进程还是获取了需要的资源。此时S->value的绝对值表示在该信号量链表中已阻塞进程的数目。
在signal操作中,先自增即释放资源,如果资源数目小于等于0,则需要唤醒链表中的进程,把它从阻塞状态改变为就绪状态。
当S->value=1,表示只允许一个进程访问临界资源此时信号量转变为互斥信号量,用于进程互斥。
3.AND型信号量
前面两个信号量只能解决多个进程对应一种资源的情况,当多个进程需要多种资源,就需要用到AND型信号量。
死锁问题:
假设两个进程A和B,都需要访问互斥型信号量Dmutex=1和Emutex=1。
process A: process B:
step1: wait(Dmutex); wait(Emutex);
step2: wait(Emutex); wait(Dmutex);
当A和B都进行完step1操作时,Dmutex=0,Emutex=0.进行step2操作时,Emutex=-1,Dmutex=-1,则A和B都被阻塞。
这时A和B就进入死锁状态。
AND型同步机制的基本思想:将进程在整个运行过程中需要的所有资源一次性全部分配给进程,待进程使用完后再一起释放。只要有一个资源未能分配给进程,其他所有可能为之分配的资源也不分配给它。
Swait(S1,S2,....Sn){while(TRUE){if(S1>=1&&S2>=1&&.....Sn>=1){for(i=1;i<=n;i++)Si--;break;}else{由于有资源未能分配给进程,其他所有资源都不分配给它}}
}
Ssignal(S1,S2,....Sn){while(TRUE){for(i=1;i<=n;i++){Si++;}}
}
4.信号量集
在上述操作中,wait和signal都只能对信号量+1和-1,也就一位置不能对临界资源进行多个单位的申请和释放。当需要N个单位的资源时,要进行N个wait操作,很低效,此外当所申请的资源数量低于某一个下限值,不予以分配,从而保证系统的安全性。
设该资源的分配下限值为ti,即最大申请值不能超过ti,对该资源申请量为di。当Si<ti,就不给分配,一旦允许分配,Si=Si-di。
Swait(S1,t1,d1,....Sn,tn,dn)
Ssignal(S1,d1,....Sn,dn)
特殊情况:
1.Swait(S,d,d)。此时在信号量集中只有一个信号量S,但允许它每次申请d个资源,当现有资源少于d时,不予分配。
2.Swait(S,1,1)。此时信号量集已经蜕化为一般的记录型信号量(S>1时)或互斥信号量(S=1时)。
3.Swait(S,1,0)。当S>=1时,允许多个进程进入某特定区;当S=0,将阻止任何进程进入特定区。
信号量的应用
1.利用信号量实现进程互斥
两个进程的互斥
设互斥信号量mutex=1,初值为1,取值范围为(-1,0,1)。当mutex=1时,表示两个进程皆未进入需要互斥的临界区;当mutex=0时,表示有一个进程进入临界区运行,另外一个必须等待,挂入阻塞队列;当mutex=-1,时,表示有一个进程正在临界区运行,另外一个进程因等待而阻塞在信号量队列中,需要被当前已经在临界区运行的进程退出时唤醒。
mutex=0和mutex=-1时都需要阻塞,但是mutex=-1时阻塞的进程需要被唤醒,即wakeup操作。
semaphore mutex=1;PA(){while(1){wait(mutex);临界区;signal(mutex);剩余区;}}PB(){while(1){wait(mutex);临界区;signal(mutex);剩余区;}}
在利用信号量机制实现进程互斥时应该注意,wait(mutex)和signal(mutex)必须成对地出现。缺少wait(mutex)将会导致系统混乱,不能保证对临界资源的互斥访问;而缺少signa(mutex)将会使临界资源永远不被释放,从而使因等待该资源而阻塞的进程小能被突。
补充:
一个访问临界资源的循环进程描述如下:
while(TRUE){进入区临界区退出区剩余区
}
在每个进程中访问临界资源的那段代码称为临界区(riticalsection)。显然,若能保证诸进程互斥地进入自己的临界区,便可实现诸进程对临界资源的互斥访问。为此,每个进程在进入临界区之前,应先对欲访问的临界资源进行检查,看它是否正被访问。如果此刻临界资源未被访问,进程便可进入临界区对该资源进行访问,并设置它正被访问的标志;如果此刻该临界资源正被某进程访问,则本进程不能进 入临界区。因此,必须在临界区前面增加一段用 于进行上述检查的代码,把这段代码称为进入区(enry section)。 相应地,在临界区后面也要加上一段称为退 出区(exit sction)的代码,用于将临界区正被访问的标志恢复为末被访间的标志。进程中除上述进入区、临界区及退出区之外的其它部分的代码在这里都称为剩余区。
2.利用信号量实现前趋关系
var a1,a2,a3,a4,a5,a6,a7:semaphore: =0;beginparbegins1:begin s1; V(a1) ; V(a2) ; ends2:begin P(a1) ; s2 ; V(a4) ; V(a5) ; ends3:begin P(a1) ; s3 ; V(a6) ; ends4:begin P(a2) ; s4 ; V(a6) ; ends5:begin P(a2) ; s5 ; V(a6) ; ends6:begin P(a3) ; P(a4) ; P(a5) ; s6 ; end
看看就懂,不过多解释。
典型例题
1.生产者——消费者问题
该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
1.利用记录型信号量解决生产者消费者问题
假定在生产者和消费者之间的公用缓冲池中具有n个缓冲区,这时可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池中取走一个消息。对生产者-消费者问题可描述如下:
int in=0, out=0;item buffer[n];semaphore mutex =l, empty=n, full=0;
void proceducer() {do {producer an item nextp;......wait(empty);//申请一个空的缓冲区wait(mutex);//申请互斥信号量,不准其他进程进入buffer[in] =nextp;//产品送入in=(in+1) % n;//下一个生产者 signal(mutex);//释放互斥信号量.准许其他进程进入signal(full);//释放一个满的缓冲区}while(TRUE);
}void consumer(){do {wait(full);//申请一个满的缓冲区wait(mutex);//申请互斥信号量,不准其他进程进入nextc= buffer[out];//产品拿出out =(out+l) % n;//下一个消费者signal(mutex);//释放互斥信号量.准许其他进程进入signal(empty);//释放一个空的缓冲区consumer the item in nextc;...}while(TRUE);
}void main {cobeginproducer();consumer();coend
}
用于实现互斥的信号量必须成对出现。
对于empty和full的wait和signal操作,也需要成对出现,但它们分别处于不同的进程中。
2.利用AND信号量解决生产者——消费者问题
int in= 0, out= 0;item buffer[n];semaphore mutex = 1, empty = n, full= 0;
void producer{do{producer an item nextp;Swait(empty, mutex);buffer[in] = nextp;in=(in+1) % n;Ssignal(mutex, full);}while(TRUE);void consumer(){do {Swait(full, mutex);nextc = buffer[out];out= (out+1)% n;Ssignal(mutex, empty);consumer the item in nextc;}while(TRUE);
}
只是把两个wait变为一个Swait,两个signal变为一个Ssignal 。
2.哲学家进餐问题
有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。
1.利用记录型信号量解决哲学家进餐问题
经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用。为了实现对筷子的互斥使用,可以使用一个信号量表示一只筷子,由这五个信号量构成信号量数组。其描述如下:
semaphore chopstick[5]={1,1,1,1,1}
所有信号量均被初始化为1,第i位哲学家的活动可以描述为:
do{wait(chopstick[i]);//拿左边筷子wait(chopstick[(i+1)%5)]);//拿右边筷子...//eat...signal(chopstick[i]);//放下左边筷子signal(chopstick[(i+1)%5]);//放下右边筷子...//think...}while(TRUE)
假如五位哲学家同时拿起左边的筷子时,就会使五个信号量chopstick 均为0:当他们再试图去拿右边边的筷子时,都将因无筷子可拿而无限期地等待。对于这样的死锁问题,可采取以下几种解决方法:
(1)至多只允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用毕时能释放出他用过的两只筷子,从而使更多的哲学家能够进餐。
(2)仅当哲学家的左、右两只筷子均可用时,才允许他拿起筷子进餐。
(3)规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子:而偶数号哲学家则相反。按此规定,将是1、2号哲学家竞争1号筷子: 3、4号哲学家竞争3号筷子。即五位哲学家都先竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。
semaphore chopstick[5]=(1, 1,1,1, 1);void philosopher(int i)while(true){if(¡ mod2 =0){//偶数哲学家,先右后左。wait (chopstick [(¡ + 1) mod 5]);wait (chopstick [ï]);eat();signal (chopstick [i);signal (chopstick[(i+ 1) mod 5]);
}else{//奇数哲学家,先左后右。wait (chopstick [i]);wait (chopstick [(i+ 1) mod 5]);eat;signal (chopstick [(i+1) mod 5]);signal (chopstick [i]);}
}
2.利用AND信号量机制解决哲学家就餐问题
利用AND信号量机制可以解决上述死锁
semaphore chopstick[5]= [1,1,1,1,1];do{//thinkSwait(chopstick[(i+ 1)%5], chopstick[i]);//eatSsignal(chopstick[(i+1)%5], chopstick[i]);}while[TRUE];
3.读者——写者问题
1.允许多个读者可以同时对文件执行读操作
2.只允许一个写者往文件写信息
3.任一写者在完成写操作之前不允许其他读者后写者工作
4.写者执行写操作前,应该让已有的读者或者写者全部退出
等我有时间补充
信号量机制以及各种例题相关推荐
- GCD之信号量机制二
在前面GCD之信号量机制一中介绍了通过信号量设置并行最大线程数,依此信号量还可以防止多线程访问公有变量时数据有误,下面的代码能说明. 1.下面是不采用信号量修改公有变量的值 dispatch_grou ...
- 十六、用信号量机制实现进程互斥、同步、前驱关系
一.知识总览 二.信号量机制实现进程互斥 注意: 1.信号量mutex表示进入临界区的名额 2.对不同的临界资源需要设置不同的互斥信号量 3.P.V操作必须成对出现,缺少P(mutex)就不能保证临界 ...
- 卡住无法查看到所有进程_进程同步 进程互斥 软件和硬件实现方式 信号量机制 信号量机制实现进程同步,进程互斥,前驱关系...
参考:https://www.bilibili.com/video/av31584226/?p=9 进程具有异步性的特征,异步性是指,各并发执行的进程以各自独立的,不可预知的速度向前推进. 回忆我们之 ...
- 操作系统(三)| 进程同步详解(主要任务、制约关系、临界资源、临界区、同步机制遵循规则、信号量机制、信号量的应用)
文章目录 进程的同步基本概念 进程同步的主要任务 进程间的制约关系 临界资源 临界区 同步机制应遵循的规则 信号量机制 整型信号量 记录型信号量 ❤❤❤ AND型信号量 信号量的应用 实现进程互斥 实 ...
- 操作系统(二十二)用信号量机制实现进程互斥、同步、前驱关系
2.3.5 用信号量机制实现进程互斥.同步.前驱关系 目录 2.3.5 用信号量机制实现进程互斥.同步.前驱关系 2.3.5.1 用信号量机制实现进程互斥 2.3.5.2 用信号量机制实现进程同步 2 ...
- 操作系统(二十一)信号量机制
2.3.4 信号量机制 在前两节中我们分别学习了用软件方式以及硬件方式实现互斥访问,但是他们或多或少的存在一些问题,1965年荷兰的一名学者迪杰斯特拉(是的,就是那个男人)提出了信号量机制,有效的解决 ...
- 2.3.5 操作系统之信号量机制实现进程的互斥、同步与前驱关系
文章目录 0.思维导图 1.信号量机制实现进程互斥 2.信号量机制实现进程同步 3.信号量机制实现前驱关系 0.思维导图 在看此小结内容之前,需熟悉这一篇博客里面的知识,关于P.V操作内部实现原理等h ...
- 2.3.4 操作系统之信号量机制(整型信号量、记录型信号量P、V)
文章目录 0.思维导图 1.为什么引入信号量机制? 2.什么是信号量机制? 3.整型信号量 4.记录型信号量 (1)举一个生动形象的例子了解记录型信号量 (2)梳理一下记录型信号量的知识点(P.V) ...
- 操作系统 第二章【记录型信号量机制、独木桥问题】【MOOC答案】
目录 第1题 第2题 第3题 第4题 第1题 1( 30分 ) 简述生产者消费者问题的解决方案,并说明用记录型信号量机制解决生产者消费者问题时Wait()操作的次序不当会在什么情况下引发死锁. 得分指 ...
最新文章
- 程序员的快速开发框架:Github上 10 大优秀的开源后台控制面板
- Linux 内核详解以及内核缓冲区技术
- 三、神兽变变变(下)
- 【Python】csv、excel、pkl、txt、dict
- android6.0源码分析之Zygote进程分析
- dw怎么在框架中加入网页_怎样使用iframe,在网页中插入页面
- 盖茨依然坐镇微软搜索团队 要与谷歌争高下
- paper 6:支持向量机系列三:Kernel —— 介绍核方法,并由此将支持向量机推广到非线性的情况。...
- 杨辉三角形(C语言)(使用一维数组的版本)
- 阿里巴巴的26款超神Java开源项目!建议收藏~
- saltstack高效运维
- php主机卫士,Bypass360主机卫士SQL注入防御八种姿势
- php实现tptp客户端
- WIDS(无线入侵检测)
- 支付宝支付(沙箱环境)
- 正定子龙大桥正式开工建设
- HTML+CSS实现(排行榜+棋盘+表格+图片商品列表)
- 贸然用string比较的后果
- DHCP动态分配ip地址
- 新型多功能6轴小型机器人
热门文章
- 华为荣耀10长按Android版本,华为荣耀10是什么系统
- SD存储卡读写速度比较
- 优化设计-有约束复合型法-MATLAB编程求解
- Python + AI人工智能——给老照片恢复色彩、上色
- k8s: the connection to the server 192.168.2.94:6443 was refused 解决方法
- 雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论
- 如何通过微信电脑客户端,快速加微信群内的好友
- 中国商业航天产业深度研究与投资方向预测报告2022-2028年版
- emWin 模拟器的使用(VS2017+Win10)
- 重复性管理——抽象的重要性(下)