【0410】饥饿和死锁

    技术2022-07-10  160

    饥饿和死锁

    死锁:多个进程在运行过程中因争夺资源或相互通信而造成的一种僵局,若无外力作用,它们都将无法再向前推进。

    可重用资源:一次仅供一个进程安全使用且不因使用而耗尽的资源。例子:处理器,I/O通道,内存和外村、设备。

    死锁例子:存储资源有限制。第二次请求无法被满足。

    可消耗资源:可被创建和销毁的资源。例子:中断、信号、消息和I/O缓冲区的消息。

    死锁例子:双方都在等在对方发消息导致死锁。

    产生死锁的条件

    资源互斥,占有且等待,非抢占----前三个条件是必要条件,也是前置条件。第四个条件—循环死锁,是充分条件。

    死锁预防

    只要打破必要条件就可以预防

    不互斥不可能,进程全部完成之后再让其他进程占领(占有且等待)低效,非抢占只适合少量资源(比如内存或CPU),循环死锁(规定顺序,进程很多,顺序难以调整)

    死锁避免

    如果一个进程的请求会导致死锁,则不启动此进程,资源启动拒绝;如果一个进程增加资源的请求会导致死锁,则不容许此分配,资源分配拒绝.

    R—系统中的每种资源的总量,V—未分配给进程的每种资源的总量,Aij----当前分配给进程i的资源j,Cij—进程i对资源j的需求

    银行家算法

    安全状态:至少有一个资源分配序列不会导致死锁

    非安全状态:非安全的一个状态 ------这个状态不代表就是死锁状态,只是有可能

    算法

    request是一个向量,定义了进程i的资源请求.

    资源分配算法:

    if(alloc(i,*)+request[*]>claim[i,*])//分配的资源大于需要的资源 <error>; else if(request[*]>available[*])//需要的资源大于可以使用的资源 <suspend process>; else{ <define newstate by: alloc[i,*]=alloc[i,*]+request[*]; available[*]=available[*]-request[*]>; } if(safe(new state)) <carrr out allocation>; else{ <restore original state>; <suspend process>; }

    测试安全算法(银行家算法):

    boolean safe(state S) { int currentavail[m]; process rest[<number of processes>]; currentavail=available; rest={all process}; possibe=true; while(possible){ <find a process PK in rest such that claim[K,*]-alloc[k,*]<=currrentavail; if(found){ currentavail=currentavail+alloc[k,*]; rest=rest-{PK}; } else possible=false;> } return (rest==null); }

    需要满足的条件:

    (1)必须事先声明每个进程请求的最大资源;

    (2)所讨论的进程必须是无关的,它们的执行顺序必须没有任何同步要求的限制;

    (3)分配的资源数量必须是固定的;

    (4)在占有资源时,进程不能退出.

    死锁检测

    是否存在死锁,不能保证死锁不发生。没有claim矩阵,请求矩阵Q,Qij表示进程i请求的j类资源的数量。

    将不是死锁的进程打上标记。

    死锁恢复

    方法:(1)取消死锁进程

    (2)回退到前面的状态

    (3)连续取消死锁进程直到不再存在死锁,遵循最小代价原则

    (4)连续抢占资源直到不再存在死锁,一个资源被抢占的进程必须回滚到获得这个资源之前

    一种综合性死锁策略:将资源分组到许多不同的资源类中;使用前面定义的防止循环等待的线性排序策略来防止资源类之间的死锁;在资源类中,使用最适合该类的算法

    哲学家就餐问题(基于管程,类似队列)

    monitor dining_controller; cond ForkReady[5]; boolean fork[5]={true};//刀叉的可用状态 void get_forks(int pid) { int left=pid; int right=(++pid)%5; if(!fork[left]) cwait(ForkReady[left]);//把左边的刀叉加入等待队列 fork[left]=false; if(!fork[right]) cwait(ForkReady[right]);//把右边的刀叉加入等待队列 fork[right]=false; } void release_forks(int pid) { int left=pid; int right=(++pid)%5; if(empty(ForkReady[left]))fork[left]=true; else csignal(ForkReady[left]); if(empty(ForkReady[right]))fork[right]=true; else csignal(ForkReady[right]); } void philosopher(k=0 to 4) { while(true) { <think>; get_forks(k); <eat>; release_forks(k); } }

    Processed: 0.009, SQL: 9