《并发编程》--22.死锁产生的条件和动静态避免死锁

来源:互联网 发布:数控编程招聘的视频 编辑:程序博客网 时间:2024/05/24 05:19

产生死锁的必要条件:


1. 互斥条件:就是一个资源同时只能有一个进程占有,不能有两个或是两个以上的占有。
2. 不可抢占条件:在一个进程所获取的资源在未使用完毕之前,资源申请者不能强行的从资源占有者手中抢夺资源。
3. 占有申请条件:进程已经占有了一个资源,但是有申请新的资源;但是新申请的资源已经被别的进程占有了,此时该进程就会阻塞,但是在获取申请的资源之前他还会一直占有已占有的那个资源。
4. 循环等待条件:存在一个循环等待序列,p1等待p2,p2等待p3,p3等待p1。形成一个进程循环等待。
上述四个条件在死锁是会同时发送,也就是只要一个必要条件不通过,则就不会产生死锁。

静态策略:避免死锁

(1)打破互斥条件:允许进程同时访问某些资源,但是,有的资源不允许被同时访问。
(2)打破不可抢占的条件:就是说允许进程强行从资源的占有者那里抢夺资源。这种方法实现起来很困难,会降低性能。
(3) 打破占有申请条件:可以实现资源预先分配策略,在进程运行前一次性向系统申请他所需要的全部资源。如果进程所需的资源不能满足,则不分配任何资源,进程暂时不运行。(问题:1.在很多时候,一个进程在执行之前不可能知道它所有的全部资源,进程在执行的过程中,是动态的。2.资源利用率低。3.降低进程的并发性,因为资源有效,有加上存在浪费,能分配的所需全部资源的进程个数必然很少。)
(4)打破循环等待条件:实行资源的有序分配策略,把资源事先分类编号,按号分配,使进程在申请,占用资源时候不能形成环路,所有进程对资源的请求必须严格按照资源号递增的顺序提出,进程占用了小号的资源,才能申请大号资源。就会形成环路。(缺点:限制进程对资源的请求,同时对系统中的所有资源合理编号也是很有困难的,增加额外的系统开销。)


动态策略:银行家算法可以避免死锁

银行家算法需要确保以下四点:

当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客顾客可以分期贷款, 但贷款的总数不能超过最大需求量
当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可- 推迟支付,但总能使顾客在有限的时间里得到贷款
当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金

实例代码如下:

/*一共有5个进程需要请求资源,有3类资源*/public class BankDemo {    /* 每个进程所需要的最大资源数 */    public static int MAX[][] = { { 7, 5, 3 }, { 3, 2, 2 }, { 9, 0, 2 },                      { 2, 2, 2 }, { 4, 3, 3 } };    /* 系统拥有的初始资源数 */    public static int AVAILABLE[] = { 10, 5, 7 };    /* 系统已给每个进程分配的资源数 */    public static int ALLOCATION[][] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },                         { 0, 0, 0 }, { 0, 0, 0 } };    /* 每个进程还需要的资源数 */    public static int NEED[][] = { { 7, 5, 3 }, { 3, 2, 2 }, { 9, 0, 2 },                       { 2, 2, 2 }, { 4, 3, 3 } };    /* 每次申请的资源数 */    public static int Request[] = { 0, 0, 0 };    /* 进程数与资源数 */    public static int   M   = 5, N = 3;    int         FALSE   = 0;    int         TRUE    = 1;    public void showdata()    {        int i, j;        System.out.print( "系统可用的资源数为:/n" );        for ( j = 0; j < N; j++ )        {            System.out.print( "资源" + j + ":" + AVAILABLE[j] + " " );        }        System.out.println();        System.out.println( "各进程还需要的资源量:" );        for ( i = 0; i < M; i++ )        {            System.out.print( "进程" + i + ":" );            for ( j = 0; j < N; j++ )            {                System.out.print( "资源" + j + ":" + NEED[i][j] + " " );            }            System.out.print( "/n" );        }        System.out.print( "各进程已经得到的资源量: /n" );        for ( i = 0; i < M; i++ )        {            System.out.print( "进程" );            System.out.print( i );            for ( j = 0; j < N; j++ )            {                System.out.print( "资源" + j + ":" + ALLOCATION[i][j] + " " );            }            System.out.print( "/n" );        }    }    /* 分配资源,并重新更新各种状态 */    public void changdata( int k )    {        int j;        for ( j = 0; j < N; j++ )        {            AVAILABLE[j]        = AVAILABLE[j] - Request[j];            ALLOCATION[k][j]    = ALLOCATION[k][j] + Request[j];            NEED[k][j]      = NEED[k][j] - Request[j];        }    };    /* 回收资源,并重新更新各种状态 */    public void rstordata( int k )    {        int j;        for ( j = 0; j < N; j++ )        {            AVAILABLE[j]        = AVAILABLE[j] + Request[j];            ALLOCATION[k][j]    = ALLOCATION[k][j] - Request[j];            NEED[k][j]      = NEED[k][j] + Request[j];        }    };    /* 释放资源 */    public void free( int k )    {        for ( int j = 0; j < N; j++ )        {            AVAILABLE[j] = AVAILABLE[j] + ALLOCATION[k][j];            System.out.print( "释放" + k + "号进程的" + j + "资源!/n" );        }    }    public int check0( int k )    {        int j, n = 0;        for ( j = 0; j < N; j++ )        {            if ( NEED[k][j] == 0 )                n++;        }        if ( n == 3 )            return(1);        else            return(0);    }    /*     * 检查安全性函数     * 所以银行家算法其核心是:保证银行家系统的资源数至少不小于一个客户的所需要的资源数。在安全性检查函数 chkerr() 上由这个方法来实现     * 这个循环来进行核心判断,从而完成了银行家算法的安全性检查工作。     */    public int chkerr( int s )    {        int WORK;        int FINISH[] = new int[M], temp[] = new int[M];     /* 保存临时的安全进程序列 */        int i, j, k = 0;        for ( i = 0; i < M; i++ )            FINISH[i] = FALSE;        for ( j = 0; j < N; j++ )        {            WORK    = AVAILABLE[j];                         /* 第 j 个资源可用数 */            i   = s;            /* 判断第 i 个进程是否满足条件 */            while ( i < M )            {                if ( FINISH[i] == FALSE && NEED[i][j] <= WORK )                {                    WORK        = WORK + ALLOCATION[i][j];                    FINISH[i]   = TRUE;                    temp[k]     = i;                    k++;                    i = 0;                } else {                    i++;                }            }            for ( i = 0; i < M; i++ )                if ( FINISH[i] == FALSE )                {                    System.out.print( "/n 系统不安全!!! 本次资源申请不成功!/n" );                    return(1);                }        }        System.out.print( "/n 经安全性检查,系统安全,本次分配成功。/n" );        System.out.print( "本次安全序列:" );        for ( i = 0; i < M - 1; i++ )        {            System.out.print( "进程" + temp[i] + "->" );        }        System.out.print( "进程" + temp[M - 1] );        System.out.println( "/n" );        return(0);    }}


原创粉丝点击