如何在 pthreads 中获取已锁定互斥量的所有线程的线程 ID

3

一个线程有一个类型为pthread_mutex_t的互斥锁,已经被锁定。另一个线程想要知道持有该锁的线程的线程ID。

据我所知,有两种类型的线程ID。一种是由pthread_self()返回的POSIX/pthread线程ID,另一种是由系统调用gettid()返回的Linux线程ID。这两种线程ID是独立的,没有关系(如有错误请纠正)。

pthread_mutex_t结构体中有一个字段int __owner,它存储着当前持有锁的线程的线程ID。可以通过以下方式访问该字段,

pthread_mutex_t mutex;
int tid;
tid = mutex.__data.__owner;

如此描述 - 是否可以确定持有互斥锁的线程?

这个__owner字段具有Linux系统线程ID(如gettid()返回的那样),而不是POSIX / pthread线程ID(如pthread_self()返回的那样)。

我想比较当前调度的线程是否拥有互斥锁。因此,我应该将pthread_self()__owner值进行比较。

我可以使用gettid()而不是pthread_self(),但我只能使用pthread_self()(一些可移植性特征)。

有没有办法正确确定锁定的互斥锁的线程ID,它会返回pthread_t而不是系统线程ID?

我将感激任何帮助,谢谢!

问候,

Yusuf Husainy。


1
既然你正在探索一个技术上不透明的对象(pthread_mutex_t),似乎担心可移植性问题有点晚了?我想你需要做的是构建一个从__owner值到pthread_self()的映射表,每个pthread在启动时都可以将自己添加到其中。(该映射表需要由互斥锁保护,在pthread“注册”自己时可以从中提取__owner值。) - user3793679
可能是重复的问题:是否有可能确定持有互斥锁的线程? 请问您的问题与您链接的那个问题有何不同之处? - alk
@alk,我理解这一点。我的问题不同在于我想知道如何获取pthread_t类型的线程ID,而不是系统TID类型的ID。链接的问题没有给出任何解决方法。 - Yusuf Husainy
那么你认为这两个问题是相同的。我怀疑你无法得到你问题的答案,因为对另一个问题的回答是没有答案。针对后者提出了解决方法。 - alk
只需编写您想要的代码。我建议使用单独的互斥锁来保护所有者变量。 - David Schwartz
2个回答

2

1)

这两者是独立的,没有关系,据我所知(如果我错了,请纠正我)。

是的。从man pthread_self中得知:

由pthread_self()返回的线程ID不同于调用gettid(2)返回的内核线程ID。

2)

因此,我应该将pthread_self()与__owner值进行比较。

不正确。根据man pthread_self

线程标识符应被视为不透明:任何尝试使用线程ID而不是在pthread调用中使用的行为都是不可移植的,并且可能导致未指定的结果。

3)

有没有办法正确确定已锁定的互斥锁的线程ID,该线程ID将返回pthread_t而不是系统线程ID?

我想没有。pthread_mutex_t具有字段int __owner;,并且没有类似于pthread_owner的字段,其中包含线程的pthread_t:

/* Data structures for mutex handling.  The structure of the attribute
   type is not exposed on purpose.  */
typedef union
{
  struct __pthread_mutex_s
  {
    int __lock;
    unsigned int __count;
    int __owner;
#if __WORDSIZE == 64
    unsigned int __nusers;
#endif
    /* KIND must stay at this position in the structure to maintain
       binary compatibility.  */
    int __kind;
#if __WORDSIZE == 64
    int __spins;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
#else
    unsigned int __nusers;
    __extension__ union
    {
      int __spins;
      __pthread_slist_t __list;
    };
#endif
  } __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;
} pthread_mutex_t;

0

这个问题可以使用堆栈跟踪来解决吗?例如,如果我在我的多线程应用程序上使用pstack命令并锁定了互斥锁,我会看到以下内容:

# pstack <PID>

Thread 3 (Thread 0x7fb94a4f4700 (LWP 25157)):
#0  0x00000034a7e0e264 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00000034a7e09508 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x00000034a7e093d7 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x000000000040af63 in read_from_pbx_loop(void*) ()
#4  0x00000034a7e079d1 in start_thread () from /lib64/libpthread.so.0
#5  0x00000034a7ae88fd in clone () from /lib64/libc.so.6
Thread 2 (Thread 0x7fb949cf3700 (LWP 25158)):
#0  0x00000034a7aaca3d in nanosleep () from /lib64/libc.so.6
#1  0x00000034a7ae1be4 in usleep () from /lib64/libc.so.6
#2  0x00000000004074f0 in read_from_agent_loop(void*) ()
#3  0x00000034a7e079d1 in start_thread () from /lib64/libpthread.so.0
#4  0x00000034a7ae88fd in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7fb94a4f6720 (LWP 25156)):
#0  0x00000034a7aaca3d in nanosleep () from /lib64/libc.so.6
#1  0x00000034a7ae1be4 in usleep () from /lib64/libc.so.6
#2  0x000000000040c600 in main ()

这样你就可以获取线程的堆栈跟踪,并使用一些简单的启发式检查,以查看线程堆栈跟踪的最后一个步骤是否为__lll_lock_wait


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接