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

The thread ID returned by pthread_self() is not the same thing as the kernel thread ID returned by a call to gettid(2)

这句话来自 man page of pthread_self()

那么,我应该根据什么来决定是用pthread_self还是gettid来判断哪个线程是运行函数?

两者都不可移植。
为什么有两个不同的函数来获取线程ID?

So, on what basis should I decide whether I should use pthread_self or gettid to determine which thread is running the function?

只要您想在应用程序中标识一个线程,就应该始终使用 pthread_self()gettid() 可以 用于某些目的 如果你知道它是 Linux。例如,gettid() 可用于获取线程特定种子的种子(在 srand() 中使用)。

Both are non portable.

这不完全正确。 gettid() 不可移植,因为它是 Linux 特定功能。但是 pthread_self() 是可移植的,只要你不对其表示做任何假设。

例如下面的不可便携

printf("Thread ID is: %ld", (long) pthread_self());

因为不能保证 pthread_self() 会是某种整数。但是

pthread_t my_tid; //filled elsewhere

pthread_t tid = pthread_self();

if( pthread_equal(my_tid, tid) ) {
   /* do stuff */
}

完全便携。

前者不可移植,因为它假定线程 ID 是整数,而后者不是。

Why are there two different functions to get the thread ID?

它们不是获得相同价值的两种不同方式。一个 (pthread_self() 由线程库 (pthreads) 提供,而另一个 (gettid() 是一个 OS 特定的函数。不同的 OS 可能提供不同的 interface/syscall 来获取类似于 gettid() 的线程 ID。因此您不能在便携式应用程序中依赖 gettid()

pthread_self() returns the process-wide unique pthread-id.

gettid() returns(特定于 pthread 实现的)系统范围的唯一线程 ID(在 Linux 上)。

the TID(thread id) returned by gettid() is unique inside a process

是的。

(or inside a program with multiple processes,

是的。

inside a process, different thread has different thread id.

是的。

the TID returned by pthread_self() is unique across processes,

没有

different thread has different TID on the same machine at the same time.

是在同一个进程,不是跨整机。

由于 gettid() 是 Linux 特定的,因此不可移植,系统广泛识别 pthread 的唯一方法是使用由 getpid() 返回的其(系统范围内唯一的)父进程 ID 以及pthread_self().

返回的(进程范围内唯一的)pthread-id

这是一项关于概念术语与真实软件实体(属于特定软件抽象)之间差异的有趣研究。

首先注意这两个调用的类型

pid_t gettid(void);
pthread_t pthread_self(void);

一个是pid_t,一个是pthread_t。这两者都指的是一个共同的概念实体,称为 thread,但不同的类型意味着它们是两个不同的 software entities。它们是 thread id 的不同表示,并且在包含它的软件抽象中有意义。因此,pthread_tpthread 包支持的抽象中 只有 有意义,而 pid_t 在包含这种类型的抽象中有意义(即Linux 处理 pid_t) 的系统调用。

您应该根据上下文使用正确的类型。在需要类型 pthread_t 的上下文中使用 pthread_t ,在需要类型 pid_t 的上下文中使用 pid_t - 不管它们可能引用同一个线程的事实。

这些上下文中的每一个都有规定的比较和相等语法。 pid_t 可以通过 == 运算符直接进行比较,而 pthread_t 必须通过调用 pthread_equal.

进行比较

这种双重表示/软件抽象的原因是 pthread 库是一个可移植的线程库,可以在不同的操作系统上实现。 pthread 库的不同实现保证 thread id 类型总是 pthread_t。这些线程可能在底层映射到操作系统特定的 thread entity,其 OS 标识符取决于操作系统(例如,对于 Linux,它是 pid_t;对于 Windows,它是 DWORD).

因此,虽然底层实现可能不同于 OS 到 OS,但针对 pthread 抽象编写的代码仍然可以跨 OSes 移植(只要你将自己局限于 pthread 抽象。