本科生操作系统原理学习记录
第六章 进程同步
6.1 竞争条件和临界区
6.1.1 竞争条件
防止竞争条件出现的有效方法包括:同步和互斥
6.1.2 临界区
一次只允许一个进程使用的资源称为临界资源,称互斥资源、独占资源或共享变量
一次允许多个进程使用的资源称为共享资源
临界区:是一个涉及临界资源的代码段
几点说明:
-
临界区是代码片段
-
临界区是进程内的代码
-
每个进程有一个或多个临界区
6.1.3 临界区使用准则
互斥:
- 假定进程
P1
在某个临界区执行,其他进程将被排斥在该临界区外 - 有相同临界资源的临界区都需互斥
- 无相同临界资源的临界区不许互斥
有空让进:
- 临界区内无进程执行,不能无限延长下一个要进临界区进程的等待时间。
- 也就是有其他进程想要进入的时候,要让他门进入
有限等待:
- 每个进程进入临界区前的等待时间必须有限
- 不能无限等待
让权等待:
- 当一个进程要进入临界区运行的时候,发现无法进入,这时候它应该主动释放CPU的控制权,让其他进程占用CPU控制权。
- running变为waiting状态
访问临界区过程
- 在进入区实现互斥准则
- 在退出区实现有空让进准则
- 每个临界区不能过大,从而实现有限等待准则
两个进程 P0 P1
,仅仅针对两个进程的算法
do {
flag[i] = true;
turn = j;
while (flag[j] and turn == j);
critical section;
flag[i] = false;
remainder section;
}while(1);
6.2 信号量(重要)
6.2.1 信号量的物理含义
保证两个或多个代码段不被并发调用
在进入关键代码段前,进程必须获取一个信号量,否则不能运行
执行完该关键代码段,必须释放信号量
信号量有值,为正说明它空闲,为负说明其忙碌
S>0:有S个资源可用
S=0:无资源可用
S<0:则|S|表示S等待队列中的进程个数
P(S):申请一个资源
V(S):释放一个资源
互斥信号量初始值:一般为1
同步信号量初始值:0-N
6.2.2 整型信号量
信号量 S——整型变量
提供两个不可分割的[原子操作]访问信号量
wait (S):
while S <= 0 do no-op;
S--;
signal(S):
S++;
Wait(S) 又称为 P(S)
Signal(S) 又称为 V(S)
整型信号量的问题:忙等
6.2.3 记录型信号量
去除忙等的信号量
记录型信号量定义:
typedef struct {
int value;
struct process *list;
} semaphore
Wait(semaphore *S)
{
S->value--;
if (S->value < 0) {
add this process to list S->list;
block(); //阻塞自身
}
}
Signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from list S->list;
wakeup(P); //唤醒的是其他进程,P变为ready状态
}
}
信号量S的使用:
- S必须置一次且只能置一次初值
- S初值不能为负数
- 除了初始化,只能通过执行P、V操作来访问S
6.2.4 互斥信号量
二值信号量也叫做互斥信号量,信号量S只能取 1 或 0
Semaphore *S;
S.value = 1; 全局变量,可以先这么理解
wait(S);
CritiaclSection() //临界区
signal();
6.2.5 同步信号量
实现各种同步问题,分散到不同的进程里面,S 的初值问题如何取值,也需要观察和思考
例子:P1
和P2
需要C1
比C2
先运行
semaphore s = 0
P1:
C1:
signal(s); //运行完了之后要告诉 C1,我运行完了
P2:
wait(s); //因为一开始 S 为0,如果C1不执行,C2就会阻塞
C2; //判断C1有没有运行
6.2.6 小例子
A B 两组同学能够轮流投球,如何实现
申请多个信号量,彼此之间交叉
semaphore s1 = 0;
semaphore s2 = 1;
A :
while(1) {
wait(S2);
C1:投球
signal(S1);
}
B:
while(1) {
wait(S1);
C2:投球
signal(S2);
}
司机 售票员问题
他们之间的同步问题是什么关系:
关好门才能启动车辆,先关门,后启动
Wait() P
Signal() V
semapheore s1 = 0
s2 = 0
司机:
P(s1)
C2: 启动车辆
正常行驶
C3: 到站停车
V(s2)
售票员:
C1: 关门
V(s1)
售票
P(s2)
C4: 开门
6.3 经典同步问题
6.3.1 生产者-消费者问题
共享有限缓冲区问题
wait的同步操作先于互斥的同步操作
问题描述
生产者(M个):生产产品,并放入缓冲区
消费者(N个):从缓冲区取产品消费
问题:如何实现生产者和消费者之间的同步和互斥
问题分析过程
生产者的生产流程:生产一个产品,然后放入缓冲区
消费者的消费流程:从缓冲区取出一个产品,消费这个产品
互斥问题分析:
互斥问题往往是在同一个进程之间产生的,而且是对临界区进行互斥操作。
如何寻找临界区呢,首先要找到临界资源,临界资源往往是一类进程进行都进行的操作但是又限制每次只能一个进程操作的范围
在本问题中,生产者的临界资源就是 放入缓冲区,消费者的临界资源就是从缓冲区取出产品
同步问题分析:
同步问题往往发生在不同类别的进程之间,一般情况是这个类别的进程进行 P 操作,S减少,就要另一个类别的进程进行V操作,把这个信号量加上去,维持平衡。
两者需要协同的部分:
- 生产者:把产品放入指定缓冲区(关键代码C1)
- 消费者:从满缓冲区取出一个产品(关键代码C2)
解决方法
变形问题:
- 缓冲区只有一个大小
- 多个不同的生产者,一个消费者 (有一个装配商,装配产品。生产商1生产一个零件,生产商2生产一个产品2,生产商3生产3,然后组装成一个产品
- 一个生产者,多个不同的消费者 (对应父亲拿水果放在盘子里,有橘子-女儿吃,苹果的话 儿子吃)
- 有几个 S 进程 发送消息,S1 and S2 发消息由 C1接收;S3 and S4发消息由C2接收
6.3.2 读者写者问题
问题描述
解决方法
设置信号量 W 为1,作为互斥信号量,作用于写者不能同时写作和读写同时
对于可以多个读者同时读的问题,再设置一个信号量 M,和计数器cnt初值为0
6.3.3 哲学家就餐问题
如果按照一般的方法进行分析,会产生死锁问题,也就是两个相邻的哲学家都选择了他们左边的筷子,这样其中就有哲学家拿不到右边的筷子,因为被其他哲学家使用了,这样就会最终导致死锁。
问题描述
5个哲学家、
5根筷子
每个哲学家左右各有一根筷子
每个哲学家只有拿起左右两个筷子才能吃饭
防止死锁的措施
方法一:只能有四个哲学家坐在桌子上吃饭
方法二:只有当哲学家的左右的筷子都可以使用的时候才能拿起筷子
方法三:给所有哲学家编号,奇数的哲学家只能首先拿起左边的筷子,偶数则反之
方法一
方法二
慕课单元作业
1、什么是临界区?对临界区的访问应该遵循什么准则?
临界区:
访问临界资源的那段代码。
准则:
-
互斥,如果有进程在某个临界区执行,其他进程将被排斥在临界区外,有相同临界资源的临界区都需要互斥,无相同临界资源的临界区不需要互斥。
-
有空让进,临界区内无进程执行,应允许一个请求进入临界区的进程立即进入自己的临界区,以有效利用临界资源。
-
有限等待,每个进程进入临界区前的等待时间必须有限,以免陷入“死等”状态。
2、请谈谈同步信号量的值有什么含义。
同步信号量的值大于0时,表示这一资源没有被使用的数量,或者释放的数量,可分配请求使用这个资源的进程。
同步信号量的值等于0时,表示这一资源分配完毕,或者没有被释放,如果现在有进程申请这个资源,必须等待。
同步信号量的值小于0时,表示请求这一资源没有得到而正在等待这一资源的数目。
3、有四个进程S1、R1、R2
和R3
,其中S1
向缓冲区BUFF发送消息,R1、R2
和R3
从缓冲区中接收消息。发送和接收的规则如下:
(1) 缓冲区BUFF任何时候只能存放1个消息;
(2) R1、R2
和R3
每次可取S1
存放在缓冲区中的消息;
(3) 每个存放在缓冲区中的消息必须被R1、R2
和R3
均接收后才能清除。
请用信号量机制来实现这4个进程间的同步。
信号量初值 S1 = 1 R1 = 0 R2 = 0 R3 = 0 MUTEX = 1
int count = 0;
S1{
R1{
R2{
R3{
P(S1); P(R1); P(R2); P(R3);
Send message; Get message; Get message; Get message;
P(MUTEX); P(MUTEX); P(MUTEX); P(MUTEX);
V(R1); count += 1; count += 1; count += 1;
V(R2); if count == 3 if count == 3 if count==3
V(R3); V(S1); V(S1); V(S1);
V(MUTEX); V(MUTEX); V(MUTEX); V(MUTEX);
} } } }
4、桌上有一个空的水果盘,且盘中一次只能放一个水果。爸爸专向盘中放苹果,妈妈专向盘中放桔子,一个儿子专等吃盘子中的桔子,一个女儿专等吃盘子中的苹果。固定每次当盘子空时爸爸或妈妈可向盘中放一个水果,仅当盘中有自己需要的水果时,儿子或女儿可从中取出。请用PV
操作实现爸爸、妈妈、儿子和女儿四个进程的同步。
信号量 Plate = 1 Orange = 0 Apple = 0
Dad{
Mum{
Son{
Daughter{
while(true){
while(true){
while(true){
while(true){
P(Plate); P(Plate); P(Orange); P(Apple);
put apple; put orange; take the orange; take the apple;
V(Apple); V(Orange); V(Plate); V(Plate);
} } eat the orange; eat the apple;
} }
} } } }
进程管理习题
设有一个可以装A 和 B两种物品的仓库,
设有两个信号量 a = N b = M
自行车生产线,三个工人进行各司其职的工作。写出进行管理问题。
某个桥很窄,只能容纳一辆小轿车行驶,从南到北,如果一方没车,另一方可以连续通过。
如果双方都有车等待,则交替通过。设每辆车为一个进程,设计信号量实现同步管理