同步互斥,死锁相关习题|信号量实现同步互斥|生产消费者模型|简答题

记录型信号量

Semaphore内部结构,是一个结构体

typedef struct
{
	int value;
	struct process *L;
}semaphore;
  • value表示资源数目
  • 如果是正数,表示当前还有多少资源可以用,如果是负数,表示还欠几个资源
  • L链表,是阻塞进程链表
semaphore S = 0;
// 等价于
semaphore S;
S.value = 0;
PV操作

PV是原语,不可被中断

void wait(semaphore S)
{
	S.value --;
	if (S.value < 0)
	{
		add this process to S.L;
		block(S.L);
	}
}

P相当于申请资源
如果申请不到,就阻塞

void signal(semaphore S)
{
	S.value ++;
	if (S.value <= 0)
	{
		remove a process P from S.L;
		wakeup(P);
	}
}

V相当于释放资源
同时唤醒被阻塞的进程

信号量相关题目

信号量实现前驱关系

![[Pasted image 20241117145730.png]]

  1. 定义信号量
    ![[Pasted image 20241117150413.png]]

一条边就是一个信号量
S1运行完成之后就会释放一个S1已经运行完的信号,就是V操作,S1运行完成后会释放一个a信号量,也要给S3释放一个b信号量
S2运行之前需要收到a信号量,来告诉S1已经运行完成了,所以S2需要申请,P一个a信号量;S2运行完毕后,需要V一下c和d
S4运行之前,需要P一下c,运行之后需要V一下e
S5运行之前,需要P一下S2的d信号量,运行之后释放一个和S6连接的g信号量
S3运行之前,要P一下和S1相连的b信号量,运行之后释放V一个和S6相连的f信号量
S6运行之前,需要P一下e,f和g信号量,S6完成之后,程序结束
2. 写PV操作

semaphore s1_2, s1_3, s2_4, s2_5, s3_6, s4_6, s5_6;
S1()
{
	// 运行S1
	...;
	V(s1_2);
	V(s1_3);
}

S2()
{
	P(s1_2);
	// 运行S2
	...;
	V(s2_4);
	V(s2_5);

}

S3()
{
	P(s1_3);
	// 运行S3
	...;
	V(s3_6)
}

S4()
{
	P(s2_4);
	// 运行S4
	...;
	V(s4_6);
}

S5()
{
	P(s2_5);
	//运行S5
	...;
	V(s5_6);
}

S6()
{
	P(s3_6);
	P(s5_6);
	P(s4_6);
	// 运行S6
	...;
}

口诀
前V后P
在前操作的后面,V一下这个信号量,在后操作的前面P一下这个信号量

一个顶点表示一个进程,有多少个顶点,就有多少个进程
一条边代表了一个约束,即需要一个信号量控制其先后关系
对于同一个信号量而言,PV操作是成双成对的,不分离的,有P就一定有V

计算填空题
  1. 有n个进程竞争某共享资源,系统允许每次最多m个进程同时使用该资源,用PV操作管理时,相应信号量可能出现的最大值是()
    信号量的值代表资源的数量
    最多允许有m个进程同时允许,一个进程使用一个资源的话,一共有m个资源,所以填入m
  2. 系统中有n个并发进程,涉及某个相同变量X,那么涉及变量X的相关临界区的个数是()
    临界区是访问临界资源的代码,访问一次临界资源就会有一个临界区
    临界资源是一次只能够让一个进程使用的临界资源,也就是共享变量X
    临界区的个数就是并发进程的数量,填入n
生产者消费者模型

超市可容纳500人同时购物,有6扇可供出入的门,既可进也可出,每扇门只允许一个人通过

  1. 用PV操作以及信号量描述进入和离开超市的算法
  2. 若规定:同一顾客进出必须通过同一扇门,那算法如何编写
    超市也就是缓冲区,6扇门是临界资源,需要设置一个互斥信号量,来互斥的使用临界资源
    ![[Pasted image 20241117185424.png]]

生产者要进入超市,要先去申请超市里的空闲资源,
互斥信号量要紧紧把互斥资源夹住,中间不能加其他信号量

// 超市中可容纳顾客数量
semaphore S = 500;
semaphore d1 = 1;
semaphore d2 = 1;
semaphore d3 = 1;
semaphore d4 = 1;
semaphore d5 = 1;
semaphore d6 = 1;

Enter()
{
	P(S);
	选择一扇门i;
	P(di);
	进入超市;
	V(di);
}

Leave()
{
	选择一扇门j;
	P(dj);
	离开超市;
	V(dj);
	V(S);
}

2
进门的时候加入一个记录变量,记录用的是哪扇门,离开的时候在从记录变量看走的是哪扇门

Enter()
{
	P(S);
	选择一扇门i;
	self.door = i; // 用变量self.door记录进入的是哪扇门
	P(di);
	进入超市;
	V(di);
}

Leave()
{
	i = self.door; // 从变量self.door得到顾客进入的是哪扇门
	P(di);
	离开超市;
	V(di);
	V(S);
}
2019

P1,P2,P3为三个相互合作的进程,P1和P2各自从外部设备读取数据分别存入X变量和Y变量,P3进程将X,Y的值相加并将结果存入Z变量
用PV操作实现上述同步关系

![[Pasted image 20241117203023.png]]

先画前趋图
P3:Z=X+Y

begin
	S1,S2:semaphore;
	S1 = 0;
	S2 = 0;

Cobegin
	processP1
	begin
		读取数据到X;
		V(S1);
	end

	processP2
	begin
		读取数据到Y;
		V(S2);
	end

	processP3
	begin
		P(S1);
		P(S2);
		Z = X + Y;
	end
Coend

end
2018

三个进程P1,P2,P3互斥使用一个包含N个单元的缓冲区,
P1每次使用"produce()"生成一个正整数并用"put()"送入缓冲区某一空单元中;
P2每次用"getodd()"从该缓冲区中取一个奇数并用"countodd()"统计奇数个数;
P3每次用"geteven()"从该缓冲区中取一个偶数并用"counteven()"统计偶数个数
用信号量机制实现这三个进程的同步与互斥活动,并说明所定义的信号量的含义

临界资源需要用Pmutex和Vmutex紧紧夹住

由于缓冲区是共享空间,设置一个互斥信号量来保护它,设信号量为mutex
P1,P2共享缓冲区的奇数数值,设同步信号量为odd
P1,P3共享缓冲区的偶数数值,设同步信号量为even
P1,P2和P3共享缓冲区的空位,设同步信号量为empty

// empty指空闲的缓冲区资源
semaphore empty = N;
semaphore full;
// 互斥信号量
semaphore mutex = 1;
semaphore odd, even = 0;

P1()
{
	生产正整数。记入x;
	x = produce();
	P(empty);
	P(mutex);
	put();
	V(mutex);
	if (x % 2 == 0)
		V(even);
	else
		V(odd);
}

P2()
{
	P(odd);
	P(mutex);
	getodd();
	V(mutex);
	V(empty);
	countodd();
}

P3()
{
	P(even);
	P(mutex);
	geteven();
	V(mutex);
	V(empty);
	counteven();
}

死锁

简答,计算,填空

死锁定义

多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进

死锁发生原因

空间

  1. 系统资源的竞争
    系统中不可剥夺资源数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局。
    只有对不可剥夺资源的竞争才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的。
    时间
  2. 进程推进顺序非法
    进程在运行过程中,请求和释放资源的顺序不当,会导致死锁。
    例如,并发进程P1,P2分别保持了资源R1,R2,而进程P1申请资源R2,进程P1请资源R2,两者都会因为所需资源被占用而阻塞,于是导致死锁。
  3. 信号量使用不当也会造成死锁
    进程间彼此相互等待对方发来的消息,也会使得这些进程间无法继续向前推进。例如,进程A等待进程B发的消息,进程B又在等待进程A发的消息,可以看出进程A和B不是因为竞争同一资源,而是在等待对方的资源导致死锁
死锁产生必要条件

虽然进程在运行过程中可能会发生死锁,但产生进程死锁是必须具备一定条件的。
综上所述不难看出,产生死锁必须同时具备下面四个必要条件,只要其中任一个条件不成立,死锁就不会发生:

  1. 互斥条件
    一进程对所分配到的资源进行排它性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其它进程请求该资源,则请求进程只能等待,直至占有该资源的进程用毕释放。
  2. 请求和保持条件
    进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放
  3. 不可抢占条件
    进程已获得的资源在未使用完之前不能被抢占,只能在进程使用完时由自己释放
  4. 循环等待条件
    在发生死锁时,必然存在一个进程一资源的循环链,即进程集合{P0,P1,…Pn},中的Pi循环占用另一个pi+1资源
处理死锁基本方法

目前处理死锁的方法可归结为四种:

  1. 预防死锁
    这是一种较简单和直观的事先预防方法。
    该方法是通过设置某些限制条件,去破坏产生死锁四个必要条件中的一个或几个来预防产生死锁。
    预防死锁是一种较易实现的方法,已被广泛使用。
  2. 避免死锁
    同样是属于事先预防策略,但它并不是事先采取各种限制措施,去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而可以避免发生死锁。
  3. 检测死锁
    这种方法无须事先采取任何限制性措施,允许进程在运行过程中发生死锁。但可通过检测机构及时地检测出死锁的发生,然后采取适当的措施,把进程从死锁中解脱出来。
  4. 解除死锁
    当检测到系统中已发生死锁时,就采取相应措施,将进程从死锁状态中解脱出来。
    常用的方法是撤消一些进程,回收它们的资源,将它们分配给已处于阻塞状态的进程,使其能继续运行。
    从(1)到(4)对死锁的防范程度逐渐减弱,但对应的是资源利用率的提高,以及进程因资源因素而阻塞的频度下降(即,并发程度提高)
死锁的处理方法(简答题)
  1. 预防死锁
    破坏产生死锁的4个必要条件中的一个或多个
  2. 避免死锁
    使用某种方法防止系统进入不安全状态,
  3. 死锁的检测和解除
    不采取任何措施,在发生死锁后,系统能够及时检测出死锁,然后采取某种措施接触死锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值