目录
示例代码
-
// DeadLock.cpp : 定义控制台应用程序的入口点。
-
//
-
-
#include <iostream>
-
#include <stdlib.h>
-
#include <thread>
-
#include <mutex>
-
-
static std::mutex mutex1;
-
static std::mutex mutex2;
-
-
static int threadFunc1()
-
{
-
std::cout <<
"Enter threadFunc1" << std::endl;
-
std::lock_guard<std::mutex> lock1(mutex1);
-
std::this_thread::
sleep_for(std::chrono::
seconds(
20));
-
std::lock_guard<std::mutex> lock2(mutex2);
-
std::cout <<
"Leave threadFunc1" << std::endl;
-
return
0;
-
}
-
-
static int threadFunc2()
-
{
-
std::cout <<
"Enter threadFunc2" << std::endl;
-
std::lock_guard<std::mutex> lock1(mutex2);
-
std::this_thread::
sleep_for(std::chrono::
seconds(
20));
-
std::lock_guard<std::mutex> lock2(mutex1);
-
std::cout <<
"Leave threadFunc2" << std::endl;
-
return
0;
-
}
-
-
int main()
-
{
-
std::thread thread1(threadFunc1);
-
std::thread thread2(threadFunc2);
-
-
thread1.
join();
-
thread2.
join();
-
-
std::cout <<
"All thread end,now exit" << std::endl;
-
return
0;
-
}
编译运行(目标程序为testDemo):./testDemo
Enter threadFunc1 Enter threadFunc2 |
并未输出:Leave threadFunc1 、 Leave threadFunc2、All thread end,now exit,随后程序处于挂起状态
分析
1、Gdb调试:gdb ./testDemo
2、 待到程序无反应时,通过Ctrl+C中断程序运行
3、查看线程信息:info threads
Id Target Id Frame * 1 Thread 0x7ffff7fdb740 (LWP 4315) "testDemo" 0x00007ffff7bbed2d in __GI___pthread_timedjoin_ex (threadid=140737335809792, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89 2 Thread 0x7ffff6e85700 (LWP 4319) "testDemo" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 3 Thread 0x7ffff6684700 (LWP 4320) "testDemo" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 |
我们看到,一共有三个线程,分别为主线程,以及两个子线程,线程号分别为4319及4320。并且两个子线程都处于锁等待的状态。
4、查看子线程4319堆栈信息:thread 2; bt(2 是相对线程号)
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 #1 0x00007ffff7bc0023 in __GI___pthread_mutex_lock (mutex=0x5555557581a0 <mutex2>) at ../nptl/pthread_mutex_lock.c:78 #2 0x00005555555550bf in __gthread_mutex_lock (__mutex=0x5555557581a0 <mutex2>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748 #3 0x0000555555555614 in std::mutex::lock (this=0x5555557581a0 <mutex2>) at /usr/include/c++/7/bits/std_mutex.h:103 #4 0x0000555555555690 in std::lock_guard<std::mutex>::lock_guard (this=0x7ffff6e84dc0, __m=...) at /usr/include/c++/7/bits/std_mutex.h:162 #5 0x0000555555555183 in threadFunc1 () at DeadLock.cpp:17 省略….. |
子线程4319在等待mutex2
5、查看子线程4320堆栈信息:thread 3; bt(3 是相对线程号)
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 #1 0x00007ffff7bc0023 in __GI___pthread_mutex_lock (mutex=0x555555758160 <mutex1>) at ../nptl/pthread_mutex_lock.c:78 #2 0x00005555555550bf in __gthread_mutex_lock (__mutex=0x555555758160 <mutex1>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748 #3 0x0000555555555614 in std::mutex::lock (this=0x555555758160 <mutex1>) at /usr/include/c++/7/bits/std_mutex.h:103 #4 0x0000555555555690 in std::lock_guard<std::mutex>::lock_guard (this=0x7ffff6683dc0, __m=...) at /usr/include/c++/7/bits/std_mutex.h:162 #5 0x000055555555529e in threadFunc2 () at DeadLock.cpp:27 |
子线程4320在等待锁mutex1
6、查看mutex1、mutex2的信息
p mutex1:
{ <std::__mutex_base> = { _M_mutex = pthread_mutex_t = { Type = Normal, Status = Acquired, possibly with waiters, Owner ID = 4319, Robust = No, Shared = No, Protocol = None } } |
p mutex2:
{ <std::__mutex_base> = { _M_mutex = pthread_mutex_t = { Type = Normal, Status = Acquired, possibly with waiters, Owner ID = 4320, Robust = No, Shared = No, Protocol = None } } |
mutex1的当前所属线程是4319(相对线程号为2),mutex2的当前所属线程是4320(相对线程号为3)。同时,mutex1及mutex2中的Status字段均表示其已经被获取,并且可能有等待者。
结论
将上述分析结果以表格形式汇总:
相对线程号 | 线程号 | 拥有锁 | 等待锁 |
2 | 4319 | mutex1 | mutex2 |
3 | 4320 | mutex2 | mutex1 |
从汇总结果看,线程4319,43202形成了死锁,导致程序挂起。
