是否有可能确定持有互斥锁的线程?
- 2024-10-22 08:28:00
- admin 原创
- 75
问题描述:
首先,我使用 pthread 库编写多线程 C 程序。线程总是被其等待的互斥锁挂起。当我使用 strace 实用程序查找FUTEX_WAIT
状态中的线程时,我想知道哪个线程当时持有该互斥锁。但我不知道该怎么做。有没有什么实用程序可以做到这一点?
有人告诉我 Java 虚拟机支持此功能,所以我想知道 Linux 是否支持此功能。
解决方案 1:
您可以使用互斥锁内部的知识来执行此操作。通常这不是一个好主意,但对于调试来说却没问题。
在 Linux 中,使用 NPTL 实现的 pthreads(任何现代的 glibc)都可以检查结构__data.__owner
的成员pthread_mutex_t
,以找出当前锁定它的线程。这是在附加到进程后使用 执行此操作的方法gdb
:
(gdb) thread 2
[Switching to thread 2 (Thread 0xb6d94b90 (LWP 22026))]#0 0xb771f424 in __kernel_vsyscall ()
(gdb) bt
#0 0xb771f424 in __kernel_vsyscall ()
#1 0xb76fec99 in __lll_lock_wait () from /lib/i686/cmov/libpthread.so.0
#2 0xb76fa0c4 in _L_lock_89 () from /lib/i686/cmov/libpthread.so.0
#3 0xb76f99f2 in pthread_mutex_lock () from /lib/i686/cmov/libpthread.so.0
#4 0x080484a6 in thread (x=0x0) at mutex_owner.c:8
#5 0xb76f84c0 in start_thread () from /lib/i686/cmov/libpthread.so.0
#6 0xb767784e in clone () from /lib/i686/cmov/libc.so.6
(gdb) up 4
#4 0x080484a6 in thread (x=0x0) at mutex_owner.c:8
8 pthread_mutex_lock(&mutex);
(gdb) print mutex.__data.__owner
$1 = 22025
(gdb)
(我切换到挂起的线程;进行回溯以找到pthread_mutex_lock()
它卡住的地方;更改堆栈框架以找出它试图锁定的互斥锁的名称;然后打印该互斥锁的所有者)。这告诉我 LWP ID 为 22025 的线程是罪魁祸首。
然后您可以使用thread find 22025
找出gdb
该线程的线程号并切换到它。
解决方案 2:
我不知道有任何这样的工具,所以我认为你不会轻易放弃——而且它在帮助调试程序方面可能没有你想象的那么有用。虽然它看起来技术含量不高,但日志记录是你调试这些东西的好帮手。开始收集你自己的小日志记录函数吧。它们不必花哨,只要能在调试时完成工作就行。
抱歉,我用的是 C++,但类似这样的代码:
void logit(const bool aquired, const char* lockname, const int linenum)
{
pthread_mutex_lock(&log_mutex);
if (! aquired)
logfile << pthread_self() << " tries lock " << lockname << " at " << linenum << endl;
else
logfile << pthread_self() << " has lock " << lockname << " at " << linenum << endl;
pthread_mutex_unlock(&log_mutex);
}
void someTask()
{
logit(false, "some_mutex", __LINE__);
pthread_mutex_lock(&some_mutex);
logit(true, "some_mutex", __LINE__);
// do stuff ...
pthread_mutex_unlock(&some_mutex);
}
记录并不是一个完美的解决方案,但没有什么是完美的。它通常能让你了解你需要知道的信息。
解决方案 3:
请阅读以下链接,这是一个查找锁所有者的通用解决方案。即使锁在库中并且您没有源代码,它也能正常工作。
https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/死锁
解决方案 4:
通常,libc/platforms 调用由 OS 抽象层抽象。可以使用所有者变量和 pthread_mutex_timedlock 跟踪互斥死锁。每当线程锁定时,它都应该使用自己的 tid(gettid() 并且还可以有另一个变量用于 pthread id 存储)更新变量。因此,当其他线程阻塞并在 pthread_mutex_timedlock 上超时时,它可以打印所有者 tid 和 pthread_id 的值。这样您就可以轻松找出所有者线程。请查看下面的代码片段,请注意,并非所有错误情况都得到处理
pid_t ownerTid;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
class TimedMutex {
public:
TimedMutex()
{
struct timespec abs_time;
while(1)
{
clock_gettime(CLOCK_MONOTONIC, &abs_time);
abs_time.tv_sec += 10;
if(pthread_mutex_timedlock(&mutex,&abs_time) == ETIMEDOUT)
{
log("Lock held by thread=%d for more than 10 secs",ownerTid);
continue;
}
ownerTid = gettid();
}
}
~TimedMutex()
{
pthread_mutex_unlock(&mutex);
}
};
还有其他方法可以找出死锁,也许这个链接可能会有帮助http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件