大致如下:首先,由于pthread_self()是在标准C库中实现的,所以不需要链接到-lpthreads。
现在,pthread_self() 使用全局变量、指向 TCB(线程控制块)的指针来存储线程信息,包括 ID(在进程中唯一)。
这个指针被初始化为 NULL (0),但是 Pthreads 库(当链接时)改变了它,所以它现在指向当前的线程头结构。
这就是为什么在不与 Pthread 链接时会得到 0,而在这样做时会得到实际的 POSIX 线程 ID。
自定义线程 ID
您可以在创建时为每个线程分配一个自定义 ID,并将该值用作数组的索引。
void* thread_function(void* data) {
assert(data);
const int id = *((int*)data);
// g_array[id]...
}
int main() {
// ...
pthread_t t0;
int t0id = 0; // this variable must exist when the thread starts
pthread_create(&t0, NULL, thread_function, &t0id);
pthread_t t1;
int t1id = 1; // this variable must exist when the thread starts
pthread_create(&t1, NULL, thread_function, &t1id);
// ...
pthread_join(t0, NULL);
pthread_join(t1, NULL);
}
另一种选择可能是使用全局std::map<pthread_t, int> g_thread_ids 结构并链接来自pthread_self() 的线程ID 和作为参数传递的数组索引。您必须小心竞争条件(为简单起见,此处省略)。您还应该关心不是以这种方式创建的线程的情况(如果可能),因为映射中不存在pthread_self() 值。
std::map<pthread_t, int> g_thread_ids;
int get_thread_index() { // note: critical section
if (g_thread_ids.find(pthread_self()) == g_thread_ids.end()) return -1;
return g_thread_ids[pthread_self()];
}
void* thread_function(void* data) {
assert(data);
const int id = *((int*)data); // read the index from caller
g_thread_ids[pthread_self()] = id; // note: critical section
// g_array[get_thread_index()]...
}