有过多线程编程经验的朋友,很多都吃过死锁的苦,如何能避免死锁,在开发中应该注意哪些问题。
有一个经验:最好不要嵌套使用同步方式。
同步的操作应该是个原子操作,要么没锁,要么锁。如果处于锁之中,那么结果就无法确定,很多时候就变成了死锁。嵌套使用就很难避免这种状况出现
死锁的主要原因是锁嵌套,多个线程在相互等资源,根据自己的经验总结了下如何尽量避免死锁:
利用OOP技术,资源尽量封装到类中。针对接口编程设计到资源的操作和访问都通过接口访问,接口内加锁,资源访问对外透明。多个线程竞争性的资源,可以适当采用单件方式。避免过多的函数嵌套。函数内使用资源尽量使用面向对象的方式管理锁的生命周期。
1.要充分考虑多个线程之间的线程调度,如下两个线程代码:线程1:Acquire Aacquire BRelease ARelease B
线程2:Acquire BAcquire ARelease BRelease A
若线程1执行完1、2两句,线程2再调度执行,或线程2执行完1、2两句,线程1再调度执行。都不会发生死锁。而若线程1执行完Acquire A时,切换到线程2执行Acquire B,此时将发生死锁。线程1等待B,线程2等待A,而B和A将永远无法释放。以上两种调度情况都有可能发生,所以会产生死锁。
2.函数进入时申请了锁,函数返回前,别忘记释放掉锁。3.若在驱动程序中使用自旋锁,必须在低于或者等于DISPATCH_LEVEL的IRQL下使用,因为线程调度是在DISPATCH_LEVEL级别完成的。否则线程得不到调度,会出现死机现显。
性能要求不是非常高的时候,可以考虑LockFree 的数据结构(可以google下),这个就不会存在锁的问题.
对性能有要求的时候,前面的朋友们都进行很细心的释了.
有锁就会有死锁,完全避免死锁的程序很难实现。在复杂的业务逻辑中,个人的经验、精力、能力有限,在如何可避免死锁上面花的精力多,势花在必业务上的心思就少了。可以看下另一种线程模型:Actor。 Erlang、Scala都有实现,Java也有一个开源项目支持:http://www.oschina.net/p/jactor
要从根本上避免,就是采用简单的线程通讯模型,比如只采用消息队列方式来通讯。在Windows平台上,采用SendMessage, PostMessage
我有一个思路,希望可以给你启发:在可能发生死锁的位置记录时间,当超过一定时间仍无法获得全部资源,则认为发生死锁。这种情况下强制释放已经占用的资源(如果已经对资源进行了处理,记得要回滚),重新申请。这么做的好处是可以有效解决已经发生的死锁。缺点是只有在某些特点条件下才能使用这种方式,同时这么做对性能等也会产生影响,并增加代码的复杂度。希望我的思路对你有帮助。
无法完全避免死锁,其实更加实际的提问方式是,如何在特定平台和系统上去检测和定位死锁?比如在android平台,经常会通过查看dataanrtraces.txt系统的日志信息来分析死锁问题。
原因很多,大部分是由于锁的使用不当造成的,下面是注意事项1. 单线程重复申请锁2. 双线程多锁申请3. 环形锁申请(也就是循环等待条件)
避免方式:
合理定义锁的粒度使用多个锁时,尽量确保所有线程都按相同的顺序获取锁,从而避免死锁。
要避免死锁先要知道死锁的原因,在网上找到了一篇说得还行的:
操作系统中有若干进程并发执行, 它们不断申请、使用、释放系统资源,虽然系统的进
程协调、通信机构会对它们进行控制,但也可能出现若干进程都相互等待对方释放资源才能
继续运行,否则就阻塞的情况。此时,若不借助外界因素, 谁也不能释放资源, 谁也不能解
除阻塞状态。根据这样的情况,操作系统中的死锁被定义为系统中两个或者多个进程无限期
地等待永远不会发生的条件,系统处于停滞状态,这就是死锁。
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足, 进程的资源请求都能够得到满足,死锁出现的可能性就很低, 否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件, 只要系统发生死锁, 这些条件必然成立, 而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防:
理解了死锁的原因, 尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以, 在系统设计、进程调度等方面注意如何不让这四个必要条件成立, 如何确
定资源的合理分配算法, 避免进程永久占据系统资源。此外, 也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。
转自:http://iask.sina.com.cn/b/1891920.html
最重要的的就是避免资源的死锁,生命周期要控制好。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
暂无简介
文章 0 评论 0
接受
发布评论
评论(11)
有一个经验:最好不要嵌套使用同步方式。
同步的操作应该是个原子操作,要么没锁,要么锁。如果处于锁之中,那么结果就无法确定,很多时候就变成了死锁。嵌套使用就很难避免这种状况出现
死锁的主要原因是锁嵌套,多个线程在相互等资源,根据自己的经验总结了下如何尽量避免死锁:
利用OOP技术,资源尽量封装到类中。
针对接口编程设计到资源的操作和访问都通过接口访问,接口内加锁,资源访问对外透明。
多个线程竞争性的资源,可以适当采用单件方式。
避免过多的函数嵌套。
函数内使用资源尽量使用面向对象的方式管理锁的生命周期。
1.要充分考虑多个线程之间的线程调度,如下两个线程代码:
线程1:
Acquire A
acquire B
Release A
Release B
线程2:
Acquire B
Acquire A
Release B
Release A
若线程1执行完1、2两句,线程2再调度执行,或线程2执行完1、2两句,线程1再调度执行。都不会发生死锁。
而若线程1执行完Acquire A时,切换到线程2执行Acquire B,此时将发生死锁。线程1等待B,线程2等待A,而B和A将永远无法释放。
以上两种调度情况都有可能发生,所以会产生死锁。
2.函数进入时申请了锁,函数返回前,别忘记释放掉锁。
3.若在驱动程序中使用自旋锁,必须在低于或者等于DISPATCH_LEVEL的IRQL下使用,因为线程调度是在DISPATCH_LEVEL级别完成的。否则线程得不到调度,会出现死机现显。
性能要求不是非常高的时候,可以考虑LockFree 的数据结构(可以google下),这个就不会存在锁的问题.
对性能有要求的时候,前面的朋友们都进行很细心的释了.
有锁就会有死锁,完全避免死锁的程序很难实现。
在复杂的业务逻辑中,个人的经验、精力、能力有限,在如何可避免死锁上面花的精力多,势花在必业务上的心思就少了。
可以看下另一种线程模型:Actor。 Erlang、Scala都有实现,Java也有一个开源项目支持:http://www.oschina.net/p/jactor
要从根本上避免,就是采用简单的线程通讯模型,比如只采用消息队列方式来通讯。
在Windows平台上,采用SendMessage, PostMessage
我有一个思路,希望可以给你启发:在可能发生死锁的位置记录时间,当超过一定时间仍无法获得全部资源,则认为发生死锁。这种情况下强制释放已经占用的资源(如果已经对资源进行了处理,记得要回滚),重新申请。
这么做的好处是可以有效解决已经发生的死锁。
缺点是只有在某些特点条件下才能使用这种方式,同时这么做对性能等也会产生影响,并增加代码的复杂度。
希望我的思路对你有帮助。
无法完全避免死锁,其实更加实际的提问方式是,如何在特定平台和系统上去检测和定位死锁?
比如在android平台,经常会通过查看dataanrtraces.txt系统的日志信息来分析死锁问题。
原因很多,大部分是由于锁的使用不当造成的,下面是注意事项
1. 单线程重复申请锁
2. 双线程多锁申请
3. 环形锁申请(也就是循环等待条件)
避免方式:
合理定义锁的粒度
使用多个锁时,尽量确保所有线程都按相同的顺序获取锁,从而避免死锁。
要避免死锁先要知道死锁的原因,在网上找到了一篇说得还行的:
操作系统中有若干进程并发执行, 它们不断申请、使用、释放系统资源,虽然系统的进
程协调、通信机构会对它们进行控制,但也可能出现若干进程都相互等待对方释放资源才能
继续运行,否则就阻塞的情况。此时,若不借助外界因素, 谁也不能释放资源, 谁也不能解
除阻塞状态。根据这样的情况,操作系统中的死锁被定义为系统中两个或者多个进程无限期
地等待永远不会发生的条件,系统处于停滞状态,这就是死锁。
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足, 进程的资源请求都能够得到满足,死锁出现的可能性就很低, 否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件, 只要系统发生死锁, 这些条件必然成立, 而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防:
理解了死锁的原因, 尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以, 在系统设计、进程调度等方面注意如何不让这四个必要条件成立, 如何确
定资源的合理分配算法, 避免进程永久占据系统资源。此外, 也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。
转自:http://iask.sina.com.cn/b/1891920.html
最重要的的就是避免资源的死锁,生命周期要控制好。