目錄
示例代碼
// 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形成了死鎖,導致程序掛起。