所谓死锁是指多个线程因竞争资源而造成的一种僵局,多个线程被无限的阻塞,线程之间相互等待所需的资源,若无外力作用,这些进程都将无法向前推进。
死锁的产生,通常是下面的两种情况:
1.如果线程试图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态,使用互斥量时,
2.如果程序使用多个互斥量时,如果允许一个线程一直占有第一个互斥量,并且在试图锁住第二个互斥量时处于阻塞状态。但是拥有第二个互斥量的线程也在试图锁住第一个互斥量,这时就会发生死锁。因为两个线程都在请求另外一个线程拥有的资源,所以这两个线程无法向前运行,于是产生死锁。这种情况用一张图表示,更加形象。如下图所示,主线程锁住互斥量L后,加锁互斥量G;同时工作线程锁住互斥量G而等待互斥量L,则产生经典的死锁现象。
针对上述类型的死锁,考虑以下两种通用的解决方法:
*固定加锁顺序:所有需要同时加锁互斥量A和互斥量B的代码,必须首先加锁互斥量A,然后加锁互斥量B
*试加锁和回退:有时候应用程序的结构使得互斥量加锁进行排序是很困难的,如果涉及了太多的锁和数据结构,可用的函数并不能把它转换成简单的层次,那么就需要采用另外的方法。可以先释放占有的锁,然后过一段时间再试。这种情况下可以使用pthread_mutex_trylock避免死锁。如果已经占有某些锁而且pthread_mutex_trylock接口返回成功,那么就可以前进;但是,如果不能获取锁,可以先释放已经占有的锁,做好清理工作,然后过一段时间重新尝试。
*固定加锁顺序:所有需要同时加锁互斥量A和互斥量B的代码,必须首先加锁互斥量A,然后加锁互斥量B
*试加锁和回退:有时候应用程序的结构使得互斥量加锁进行排序是很困难的,如果涉及了太多的锁和数据结构,可用的函数并不能把它转换成简单的层次,那么就需要采用另外的方法。可以先释放占有的锁,然后过一段时间再试。这种情况下可以使用pthread_mutex_trylock避免死锁。如果已经占有某些锁而且pthread_mutex_trylock接口返回成功,那么就可以前进;但是,如果不能获取锁,可以先释放已经占有的锁,做好清理工作,然后过一段时间重新尝试。
那么死锁产生了,如何得知程序的死锁在哪,该如何调试呢?
在linux平台下,可以使用 pstack 和 gdb 工具对死锁程序进行分析。
如果有生成core文件,则可以输入 gdb 执行文件名 core,然后在gdb下thread apply all bt
如没有core文件:
如没有core文件:
gdb调试线程死锁,还有检测死锁,可以看看另外两篇文章。1.运行程序,让程序挂起2.查找进程id ps -e | grep 程序名4.启动gdb attach 进程gdb attach 进程ID5.info threads (显示所有线程信息 )6. thread 2 (跳到第2个线程 )7.bt (跳到第2个线程 )
使用gdb调试死锁线程 : http://blog.csdn.net/atinybirdinit/article/details/41550149