操作系统(七) -- 死锁

1. 由一个示例引出死锁

多个进程在交替执行的时候,如果控制不好,就会出现死锁的情况;这个问题需要操作系统去处理。

Producer(item)
{
	P(mutex);		
	P(empty);

	// 代码

	V(mutex);
	V(full);
}

Consumer()
{
	P(mutex);
	P(full);

	// 代码

	V(mutex);
	V(empty);
}

一种可能的调用顺序如下:
当mutex=1,empty=0时,首先Producer(),然后Consumer;

mutex=1,empty=0;首先调用Producer(),P(empty)的时候发现empty已经为0,进入睡眠。这时候无论调用多少个Producer进程都会进入睡眠;如果调用Consumer()进程,因为mutex为1,前面调用producer()的时候已经P(mutex)了,在Consumer中再次P(mutex),那么Consumer进程会睡眠;这时候无论来多少个Consumer都会睡眠。

那么Producer什么才能wakeup呢?当V(mutex)时,但是V(mutex)在Consumer中,而且Consumer进程会在P(mutex)的时候就睡眠。也就是Consumer持有Producer所需要的资源不释放,导致Producer无法执行。换个角度,为什么Consumer会不执行呢?也是因为Producer持有Consumer资源不释放导致的。

2. 死锁

2.1 定义

死锁是指由于两个或者多个进程互相持有对方所需要的资源,导致这些进程处于等待状态,无法前往执行。

2.2 产生的后果

CPU利用率下降,也就是电脑会变卡。

2.3 成因

1)资源是互斥的,一旦占有别人无法使用。
比如某个Producer进程sleep了,无法V(mutex);其他的Producer进程不能绕过前面P(mutex)而直接执行V(mutex);

2)进程占有了资源,不释放就再去申请资源。
一个Producer进程P(mutex)占有了mutex资源,但是没有V(mutex);其他的Producer进程仍然P(mutex),无法V(mutex);

2.4 四个必要条件

1)互斥使用
资源的固有特性

2)不可抢占
资源只能自愿放弃,无法抢占

3)请求和保持
首先占有资源,不释放,再去申请资源

4)循环等待

2.5 处理方法

2.5.1 死锁预防

这里介绍两种方式,
方式一:一次性申请所有需要的资源。这样就不会占有资源再去申请其他资源了。破坏了必要条件3。
但是这种方式存在很大的不足:
第一点:在程序运行前就要知道这个程序会申请多少资源,需要预知未来,变成困难
第二点:可能许多资源分配后很长时间后才使用,资源利用率低

方式二:资源按顺序申请,这种方式不会造成环路等待。假设有十个资源,申请的时候必须按照顺序申请,需要资源1就申请资源1,需要资源2就申请资源2,但是如果需要使用资源10,就必须将前面的资源都申请了;但是也会造成很大的资源浪费。

从这里也能看到,死锁预防的方法并不好。

2.5.2 死锁避免

如果系统中的所有进程存在一个可完成的执行序列P1…Pn,则称系统处于安全状态。那这个安全序列怎么找到呢?使用银行家算法


P0到P4表示五个进程,ABC表示三种资源,ABC下面的数字表示对应的资源个数,Allocation表示当前进程占用的资源,Need表示该进程执行需要用的资源,Available表示系统剩余的资源。

银行家算法大意是:如果P1要执行,那么假设让P1执行一下,如果P1执行之后没有死锁,没问题;那就让P1执行。如果P1执行之后引起死锁了,那就不让P1执行。这就是死锁避免。

m 表示资源数量,n表示进程个数

int Available[1...m] ;//每种资源剩余数量
int Allocation [ 1...n, 1...m] ;//己分配资源数量
int Need [ 1..n, 1..ml;//进程还需的各种资源数量
int Work [ 1..m] ;//工作向量
bool Finish  [ 1..n] ;//进程是否结束

Work=Available;Finish[1..n]=false;
while(true){
    for (i=1;i<=n; i++)
	{
		if(Finish[i]==false && Need [i] <= Work[i] )
		{
			Work=Work+Allocation[i];
			Finish[i]=true;  break; 
		}
		else
		{
			goto end;
		}
    )
)
End:
	for (i=1;i<=n; i++)
	  	if(Finish[i]==false)return "deadlock";

银行家算法的时间复杂度是O(mn^2);如果每次申请资源都调用一次,那么系统的开销太大了。

2.5.3 死锁检测+恢复

因为银行家算法的效率太低了,所以采取检测+恢复的方式。定时检测或者资源利用率低的时候检测。但是检测到某些进程死锁之后如何处理呢?回滚?回滚需要机制的支持;而且如果是一些文件修改的进程呢?所以也不好处理。

2.5.4 死锁忽略

碰见死锁直接忽略,这才是windows和Linux采用的机制;因为死锁本来就是小概率事件,而且重启可以解决这个问题,对于个人PC机来说,一般也不会造成很大影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值