死锁,死锁必要条件及处理策略

多线程中,常见的一种问题除了竞态条件外就是死锁。

那什么是死锁呢?死锁就是:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。

那么为什么会产生死锁呢?

1.因为系统资源不足。
2.进程运行推进的顺序不合适。
3.资源分配不当。

这个定义可能有点拗口,一个最简单的例子就是有资源A和资源B,都是不可剥夺资源,现在进程C已经申请了资源A,进程D也申请了资源B,进程C接下来的操作需要用到资源B,而进程D恰好也在申请资源A,那么就引发了死锁。这个肯定每个人都看过了。然后套用回去定义:如果一个进程集合里面(进程C和进程D)的每个进程(进程C和进程D)都在等待只能由这个集合中的其他一个进程(对于进程C,他在等进程D;对于进程D,他在等进程C)才能引发的事件(释放相应资源)。

这里的资源包括了软的资源(代码块)和硬的资源(例如扫描仪)。资源一般可以分两种:可剥夺资源(Preemptable)和不可剥夺资源(Nonpreemptable)。一般来说对于由可剥夺资源引起的死锁可以由系统的重新分配资源来解决,所以一般来说大家说的死锁都是由于不可剥夺资源所引起的。

学过操作系统的朋友都知道:产生死锁的条件有四个:

1.互斥条件:所谓互斥就是进程在某一时间内独占资源。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

处理死锁的策略:

1.忽略该问题。例如鸵鸟算法,该算法可以应用在极少发生死锁的的情况下。为什么叫鸵鸟算法呢,因为传说中鸵鸟看到危险就把头埋在地底下,可能鸵鸟觉得看不到危险也就没危险了吧。跟掩耳盗铃有点像。
2.检测死锁并且恢复。
3.仔细地对资源进行动态分配,以避免死锁。
4.通过破除死锁四个必要条件之一,来防止死锁产生

 

 

windows 多线程编程的几点经验 (防止死锁)

1) 不要在线程函数体内操作MFC控件,不要再线程里面调用UpdateData函数更新用户界面,而应该尽量采用发送消息的方式,在主线程的消息响应函数中操作控件;

2)不建议采用SendMessage往主线程发送消息,因为它是同步的,阻塞的,可以考虑采用PostMessage代替;

3)线程退出时,尽量不要使用TerminateThread函数,而尽可能的让线程自己退出;

4) 当线程退出时,必须先等待工作者线程退出,主线程才退出,但是在主线程里面不要使用WaitForSingleObject或WaitForMultiObjects等待线程结束,因为它可能造成死锁,当主线程使用这两个函数时,主线程就挂起了,尤其在第 (1), (2) 种情况下,工作者线程还在调用主线程里面的资源,这样造成死锁;

5) 为了防止退出死锁的发生,尽量使用MsgWaitForMultipleObjects函数,因为该函数等待时,可以等待线程句柄 有信号,而且还可以等待消息,不会造成死锁;

1. 原子访问:(从来不会把线程切换到等待状态)
InterlockedExchangeAadd; // 原子加减
InterlockedIncrement;
InterlockedExchange; // 原子赋值 应用:旋转锁(少用)
InterlockedExchangePointer;

2. 高速缓存行:
CPU会将所要取的内存数据的临近数据存到高速缓存行,因此将只读和可读写的数据适当分开组织可提高性能。
指针永远不需要volatile关键字修饰,因为会永远读取内存地址,编译器不会做任何优化。

3. 高级同步
关键段(critical section):锁代码(只能在同一个进程中同步,无法指定最长等待时间:容易死锁)
如果有全局CRITICAL_SECTION对象,则可以用它锁不同的代码段;
EnterCriticalSection和LeaveCriticalSection;
必须初始化和反初始化:IntializeCriticalSection和DeleteCriticalSection;
优点:内部使用Interlock函数,速度快;
缺点:无法用来在多个进程之间对进程进行同步;

多处理器调用没有问题,只有一个处理器的线程能执行,其余都要等待;
由于线程进入等待状态要被系统从用户态切换到内核态,因此在使用关键段是应该总是同时使用旋转锁:
IntializeCriticalSectionAndSpinCount,旋转锁循环次数经典值是4000;
Slim读/写锁

以上方法的线程同步将保证线程在用户态:速度快。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值