我正在研究以下功能。这个函数应该创建n个线程。它也应该打印子线程的tid。但此刻我有点困惑。当我执行它并且例如我创建5个线程时,它会一直返回相同的tid。据我所知,tid是调用者的线程ID。同一个调用者是否调用了所有这些线程,或者我做错了什么。 这是代码:
void spawnThreads( unsigned int n) {
int threads = n, ret = -1;
pthread_t * thread = malloc(sizeof(pthread_t)*threads);
pid_t tid;
int i;
for(i = 0; i < threads; i++) {
ret = pthread_creation(&thread[i], NULL, (void *(*)(void *)) foo, NULL); // foo does not do anything
if( ret != 0) {
printf("pthread error!\n");
}
tid = syscall(SYS_gettid);
printf("%d %d\n", i, tid);
printf("I just created thread %d\n", i);
pthread_join(thread[i],NULL);
}
void * foo(void) {
return NULL;
}
例如,我得到以下输入 spawnThreads(4) 以下输出:
0 2411
I just created thread 0
1 2411
I just created thread 1
2 2411
I just created thread 2
3 2411
I just created thread 3
总之,该功能应打印&gt; i&lt; &GT; TID&LT; 即可。 &gt; tid&lt; 表示儿童的TID,&gt; i&lt; 从1运行到n。
但为什么我会得到相同tid的四倍?我做错了什么?如果有人能解释我出了什么问题,我将不胜感激。
答案 0 :(得分:4)
您为每个线程获得相同TID的原因是您每次都从主线程调用syscall(SYS_gettid)
,而不是从您创建的新线程中调用struct s_threadId {
pthread_mutex_t mtx; /* mutex & condition to allow main thread to
wait for the new thread to set its TID */
pthread_cond_t cond; /* '' */
pid_t id; /* to hold new thread's TID */
int ready; /* to indicate when 'id' is valid, in case
the condition wait gets interrupted */
};
。您需要从线程函数内部调用它,然后提供一种方法将信息传递回主线程(如果需要)。
作为一种方法的例子(省略了一些错误检查):
创建一个结构来保存互斥锁,条件,TID和一个标志,以指示TID何时有效。
spawnThreads()
然后将您的线程函数更改为锁定,设置和发信号(并移动它以使其声明在 void *foo(void *arg)
{
struct s_threadId *thId = arg;
/* Lock mutex... */
pthread_mutex_lock(&thId->mtx);
/* Get and save TID and ready flag.. */
thId->id = syscall(SYS_gettid);
thId->ready = 1;
/* ..and signal main thread that we're ready */
pthread_cond_signal(&thId->cond);
/* ..then unlock when we're done. */
pthread_mutex_unlock(&thId->mtx);
/* ... */
return NULL;
}
之前可见):
spawnThreads
...并修改你的void spawnThreads(unsigned int n)
{
pthread_t thread; /* reused for each thread, since they run 1 at a time */
/* struct to pass back TID */
struct s_threadId threadId;
pthread_cond_init(&threadId.cond, NULL); /* init condition */
pthread_mutex_init(&threadId.mtx, NULL); /* init mutex */
int i;
for (i = 0; i < n; i++) {
/* lock mutex *before* creating the thread, to make the new thread
wait until we're ready before signaling us */
pthread_mutex_lock(&threadId.mtx);
/* clear ready flag before creating each thread */
threadId.ready = 0;
/* create threads and pass address of struct as argument */
if (pthread_create(&thread, NULL, foo, &threadId)) {
printf("pthread error!\n");
} else {
/* Wait on the condition until the ready flag is set */
while (!threadId.ready) {
pthread_cond_wait(&threadId.cond, &threadId.mtx);
}
/* Now we have the TID... */
printf("%d %d\n", i, threadId.id);
printf("I just created thread %d\n", i);
}
/* ..and unlock the mutex when done. */
pthread_mutex_unlock(&threadId.mtx);
pthread_join(thread, NULL);
}
/* When we're completely done with the struct we need to clean up the
mutex and condition variable */
pthread_mutex_destroy(&threadId.mtx);
pthread_cond_destroy(&threadId.cond);
}
函数来初始化/清理struct成员并在线程设置后获取TID:
{{1}}
在上面,需要互斥和条件等待,以确保主线程不会尝试打印TID,直到新线程有机会设置它。主线程启动新线程然后等待,新线程在完成存储TID时发出信号,以便主线程可以继续。
答案 1 :(得分:1)
有三个人通常感兴趣的信息:进程ID,线程ID和pthreads线程id。所有pthread
调用都是自包含的,因为它们使用自己的线程ID。由于pthreads API之外的原因,进程ID和os线程ID可能很重要。
Pthread ID由pthread_create
和pthread_self
报告,前者报告它创建的线程,后者报告本身。否则就是鸡蛋和鸡蛋的情况。一个线程不能向另一个线程询问它的id是什么,除非它已经知道它的id是什么。如果这很重要,必须建立一些机制,全局列表,一些IPC等来实现它。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <string.h>
typedef struct
{
int i;
pid_t pid; // linux pid
pid_t tid; // linux thread id
pthread_t ptid; // pthreads tid
} data;
void *foo(void *args)
{
data *p = (data *) args;
p->pid = getpid();
p->tid = syscall(SYS_gettid);
p->ptid = pthread_self();
return(p);
}
void spawnThreads(unsigned int numThreads)
{
int ret;
pthread_t *tids = malloc(sizeof(pthread_t) * numThreads);
int i;
for (i = 0; i < numThreads; i++)
{
data *dp = malloc(sizeof(data) * numThreads);
memset(dp, '\0', sizeof(*dp));
dp->i = i;
ret = pthread_create(&tids[i], NULL, foo, (void *) dp);
if ( ret != 0)
perror("pthread create error");
}
for (int i = 0; i < numThreads; ++i)
{
data *status;
ret = pthread_join(tids[i], (void *) &status);
if ( ret != 0)
perror("pthread join error");
else
{
printf("thread num %d joined and reports pthreadId of %lu "
"process pid of %d and linux tid of %d\n",
status->i, status->ptid, status->pid, status->tid);
free(status);
}
}
free(tids);
}
int main(int argc, char *argv[])
{
printf("main thread reports pthreadId of............ %lu "
"process pid of %d and linux tid of %ld\n",
pthread_self(), getpid(), syscall(SYS_gettid));
spawnThreads(5);
return (0);
}