您好,欢迎来到思海网络,我们将竭诚为您提供优质的服务! 诚征网络推广 | 网站备案 | 帮助中心 | 软件下载 | 购买流程 | 付款方式 | 联系我们 [ 会员登录/注册 ]
促销推广
客服中心
业务咨询
有事点击这里…  531199185
有事点击这里…  61352289
点击这里给我发消息  81721488
有事点击这里…  376585780
有事点击这里…  872642803
有事点击这里…  459248018
有事点击这里…  61352288
有事点击这里…  380791050
技术支持
有事点击这里…  714236853
有事点击这里…  719304487
有事点击这里…  1208894568
有事点击这里…  61352289
在线客服
有事点击这里…  531199185
有事点击这里…  61352288
有事点击这里…  983054746
有事点击这里…  893984210
当前位置:首页 >> 技术文章 >> 文章浏览
技术文章

unix上防止程序死锁的一些手段

添加时间:2011-4-29  添加: admin 

在unix上做C的开发已经快2年了,一直在我们部门的一个主要产品项目组工作,该产品在市场上经受了一年半的考验,可以说已经是很成熟的产品了,该产品在大部分客户那里一直稳定的运行,没有任何问题,而在少数几个客户那里,时不时的出现整个系统的吊死,而且该问题没有任何规律可寻,除了系统吊死时候,我们对整个系统用pstack进行所有进程堆栈的跟踪记录外,我们没有任何其它线索,没有系统崩溃时候产生的CORE,我们开始面对来自客户强大的压力。。。。我们几乎喘不过起来,我们要给客户提交故障报告,而这些故障报告的问题都是这一个问题,这个问题开始成为悬在我们头上的一把利剑。

我开始被指派来解决这个问题。其实我们很早的就从进程的堆栈跟踪里知道这个问题是死锁问题,但是,它是怎么发生的那,我们几乎排查了整个系统的代码,但是一无所获。。。

在今年大年初一的时候,我们的系统又一次出现了该问题,当接到我们维护工程师的电话的时候,我的心情非常的沉重,我没有做到我作为一个程序员应有的职责,还是象往常一样,除了进程堆栈跟踪外,我没有任何其它线索,我还是照例接收邮件,查看我们维护工程师发回来的堆栈跟踪记录,可能是过年放假在家里休息了一段时间的缘故,脑袋好像特别清醒,面对堆栈跟踪记录,结合源码,我迅速的意识到造成死锁的原因是经典的竞态条件问题,是一个进程准备退出的时候,它会唤醒它里面的一个线程,该线程首先会获得一个锁,进行后续出来,然后解锁退出,但是由于该进程的主线程没有采用任何方式来等待该线程的退出,而是直接通过return的方式进行了退出,我们知道,当主线程退出的时候,操作系统会直接终止该进程里面的其它线程,不会留任何机会让那个线程做退出处理。而那个线程可能恰恰刚刚获的了锁,而还没来得及解锁,就被扼杀了,于是就造成了其它进程或线程再加这个锁的时候,就会被阻塞,系统死锁问题也就浮现了出来。

当然,我知道了是竞态条件问题造成了死锁,就会通过pthread_join来同步等待那个线程退出,来消除这个竞态条件,也就消除了死锁,问题其实也就解决了。但是,我们有没有办法来消除由于一个锁的owner没有释放该锁,就死掉了,其它线程再加这个锁的时候而造成的死锁问题那?

关于上面这个问题,我曾经在chinaunix请教过很多人,有的人想通过一个网络锁(就是加锁、解锁都要访问网络上的一台机器)来解决,但是这些方法都不成熟,也很复杂,也好像有高手对这个问题不屑。我通过搜集很多资料发现,原来解决这个问题非常的简单,简单的不能在简单了。

在很多系统上,当一个锁的owner没有释放该锁,就退出了,那么默认的方式就是其它线程再去加这个锁的时候,就会阻塞,造成死锁。而通过不同的属性初始化这个锁,我们能够改变这种默认的方式:

pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
pthread_mutexattr_setrobust_np(&mattr,PTHREAD_MUTEX_ROBUST_NP);

通过设置锁的上面两个属性,我们就改变了默认的行为,当一个锁的owner死掉后,其它线程再去加这个锁的时候,不会被阻塞,而是通过返回值EOWNERDEAD来报告错误,那么你可以根据这个错误来进行处理:首先是应该调用pthread_mutex_consistent_np函数来恢复该锁的一致性,然后调用解锁pthread_mutex_unlock,接下来在调用加锁,这样该锁的行为就恢复正常了。如果上面这个函数在恢复锁的一致性时候没有成功,那么你只需要调用解锁函数就OK了,然后直接返回,而不要去调用加锁函数,那么接下来的线程在调用加锁函数的时候,会得到返回值ENOTRECOVERABLE,那么需要你做的就是调用pthread_mutex_destroy来destroy掉该锁,然后重新用锁的属性和锁的初始化函数来重新初始化该锁。

上面的这些解决死锁方式比较适合在系统中只有一个锁的情况,如果系统的死锁是由于多把锁的资源互相等待而造成的,那么这种解决方式无能为力。。。

注:上面有一些函数后面有np后缀的,表示not portable,就是不可移值的意思,这些函数是一些系统自己实现的,而不是POSIX标准。

关键了:程序、系统、POSIX

分享到:

顶部 】 【 关闭
版权所有:佛山思海电脑网络有限公司 ©1998-2024 All Rights Reserved.
联系电话:(0757)22630313、22633833
中华人民共和国增值电信业务经营许可证: 粤B1.B2-20030321 备案号:粤B2-20030321-1
网站公安备案编号:44060602000007 交互式栏目专项备案编号:200303DD003  
察察 工商 网安 举报有奖  警警  手机打开网站