Linux编程学习之线程篇-Mutex的死锁

来源:互联网 发布:ggplot python 编辑:程序博客网 时间:2024/06/15 00:59

互斥量,也叫互斥锁。通常造成死锁的有两种方式:

l  .线程A试图对用一个互斥量mutexA加锁两次,那么它自身就会陷入死锁状态

用伪代码表示:

1.  pthread_mutex_lock(&mutexA)  

2. pthread_mutex_lock(&mutexA) /* 这里死锁 */  

l  程序中使用多个互斥量时,如果允许一个线程一直占有第一个互斥量,并且试图锁住第二个互斥量时处于阻塞状态,但是拥有第二个互斥量的线程也在试图锁住第一个互斥量,这时就发生死锁。因为两个线程都在互相请求另一个线程拥有的资源,所以这两个线程都无法向前运行,于是产生死锁。

用伪代码表示:

pthreadA:

1.  pthread_mutex_lock(&mutexA)  

2. pthread_mutex_lock(&mutexB) /* 这里死锁 */  

pthreadB:

1.  pthread_mutex_lock(&mutexB)  

2. pthread_mutex_lock(&mutexA) /* 这里死锁 */  

避免死锁的算法:

有序资源分配法
这种算法资源按某种规则系统中的所有资源统一编号(例如打印机为1、磁带机为2、磁盘为3等等),申请时必须以上升的次序。系统要求申请进程:
1、对它所必须使用的而且属于同一类的所有资源,必须一次申请完;
2、在申请不同类资源时,必须按各类设备的编号依次申请。

例如:

进程PA,使用资源的顺序是R1R2

进程PB,使用资源的顺序是R2R1

若采用动态分配有可能形成环路条件,造成死锁。
采用有序资源分配法:R1的编号为1R2的编号为2
PA:申请次序应是:R1R2
PB
:申请次序应是:R1R2
这样就破坏了环路条件,避免了死锁的发生。

银行算法
避免死锁算法中最有代表性的算法是DijkstraE.W于1968年提出的银行家算法:
该算法需要检查申请者对资源的最大需求量,如果系统现存的各类资源可以满足申请者的请求,就满足申请者的请求。
这样申请者就可很快完成其计算,然后释放它占用的资源,从而保证了系统中的所有进程都能完成,所以可避免死锁的发生。

在《UNIX环境高级编程》一说中说道,如果出现死锁的情况,可以先释放占有的锁,做好清理工作,然后过段时间再试一次。

 

优先级反转:

优先级反转是指一个低优先级的任务持有一个被高优先级任务所需要的共享资源。高优先任务由于因资源缺乏而处于受阻状态,一直等到低优先级任务释放资源为止。而低优先级获得的CPU时间少,如果此时有优先级处于两者之间的任务,并且不需要那个共享资源,则该中优先级的任务反而超过这两个任务而获得CPU时间。如果高优先级等待资源时不是阻塞等待,而是忙循环,则可能永远无法获得资源,因为此时低优先级进程无法与高优先级进程争夺CPU时间,从而无法执行,进而无法释放资源,造成的后果就是高优先级任务无法获得资源而继续推进。

解决方案:

1)设置优先级上限,给临界区一个高优先级,进入临界区的进程都将获得这个高优先级,如果其他试图进入临界区的进程的优先级都低于这个高优先级,那么优先级反转就不会发生。

2)优先级继承,当一个高优先级进程等待一个低优先级进程持有的资源时,低优先级进程将暂时获得高优先级进程的优先级别,在释放共享资源后,低优先级进程回到原来的优先级别。嵌入式系统VxWorks就是采用这种策略。

原创粉丝点击