来源:
【Linux】线程安全:死锁(附加gdb调试分析)_gdb查看死锁-CSDN博客
死锁的产生场景
情况1:线程加锁后,并没有释放互斥锁
模拟代码:
结果分析:
死锁的gdb调试分析
上述情况分析,并不是很明确,通过gdb调试,观察发生死锁前,每个g_lock
被哪个线程所持有,即可更加清晰的分析。
gdb调试指令
首先需下载gdb工具(通过包管理器进行安装)
yum -y install gdb
查看GDB版本:gdb -v
gdb调试的必须是debug文件
,但编译器默认生成release文件
,若想调试,必须在编译命令后添加-g
,告诉编译器在编译程序时加入调试信息:
gcc -g $^ -o $@
- 启动gdb:
gdb test.exe
- 打断点:
(gdb)break (b)
// 启动gdb
gdb test.exe
-----------------------------------------------
// 查看源码和行号:(gdb)list (l)
l + 开始行数,默认显示十行
-----------------------------------------------
// 打断点:(gdb)break (b)
// 根据行号设置断点
(gdb) b 5
// 根据函数设置断点
(gdb) b main
// 根据条件设置断点
(gdb) b test.c:10 if a == 1
// 设置临时断点(只生效一次)
(gdb) tbreak test.c:12// 显示所有断点
(gdb) info breakpoints// 清除断点
// 清除某个断点
(gdb) delete 4
// 清除所有断点
(gdb) delete
// 清除当前行断点
(gdb) clear
-----------------------------------------------
// 运行和继续
// 运行(按断点)
(gdb) run (r)
// 继续执行到下一个断点
(gdb) continue (c)
// 逐语句调试
(gdb) next (n)
// 逐步调试(进入函数体)
(gdb) step(s)
// 跳出函数体(执行到指定行)
(gdb) until (u)
// 跳转指定位置
(gdb) jump(j)
-----------------------------------------------
// 打印变量
(gdb) print (p)
-----------------------------------------------
// 终止调试
(gdb) quit (q)
-----------------------------------------------
// 显示调用堆栈
// 显示当前执行线程
bt
// 跳转线程
t + 线程号
// 显示当前进程所有线程
thread apply all bt
调试示范
为上述的case_2
进行gdb调试分析:
不打断点,直接r运行:
死锁的必要条件
互斥条件:
一个互斥锁,同一时间只能被一个线程持有(属性条件,无法改变);
不可剥夺:
线程获得互斥锁后,只能自己释放,其他线程不能释放(属性条件,无法改变);
循环等待:
所有的线程都在等待一个锁,而这个锁被另一个线程所持有,且这种关系形成一个闭环;
请求与保持:
一个线程拿到了部分锁,若还需要锁,并不会释放已获得的锁,而是阻塞等待;
上述四个条件须同时满足,才会发生死锁;
死锁的预防措施
本文来源: