给出以下代码
#include <pthread.h>
void *pt_routine(void *arg)
{
pthread_t *tid;
tid = (pthread_t *) arg;
/* do something with tid , say printf?*/
/*
printf("The thread ID is %lu\n", *tid);
*/
return NULL;
}
int main(int argc, char **argv)
{
int rc;
pthread_t tid;
rc = pthread_create(&tid, NULL, pt_routine, &tid);
if (rc)
{
return 1;
}
printf("The new thread is %lu\n", tid);
pthread_join(tid, NULL);
return 0;
}
例程总是可以得到正确的tid
吗?
当然我可以使用pthread来获取自我ID,但我只是想知道例程何时运行。
答案 0 :(得分:4)
嗯,实际上有两个问题:
这个答案涉及Linux,因为我没有任何其他平台可用。可以找到第一个问题的答案in the manuals:
除非是实时的 呼叫后,正在使用调度策略
pthread_create()
,它是不确定的线程 - 调用者或者 新线程将在下一次执行。
所以很明显,在你的情况下,首先实际运行哪个线程是不确定的。现在,另一个问题是如何实现pthread_create
- 如果它可以以某种方式创建一个休眠线程,首先存储它的id,然后再启动它?
好吧,linux使用clone
系统调用创建新线程:
clone(child_stack=0x7f7b35031ff0,
flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM
|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
parent_tidptr=0x7f7b350329d0,
tls=0x7f7b35032700,
child_tidptr=0x7f7b350329d0) = 24009
现在,似乎线程ID与clone
调用的指针一起存储,但似乎child_tidptr
没有引用地址{ em> tid
,好像我打印它,地址不同;这是pthread
库中的一些内部变量;在 tid
系统调用在父线程中返回后,clone
将更新。
事实上,pthread_self
说的如下:
pthread_self()
返回的线程ID不是一回事 作为调用gettid(2)
返回的内核线程ID。
这确认了内核线程ID与pthread_t
s
因此,除了POSIX spec不支持这一点之外,Linux平台上实际上没有这样的保证 - 需要在父线程中设置tid
<{1}}返回后,否则父不会立即知道孩子的线程ID - 但这也意味着如果孩子是第一个执行后的孩子返回,那么线程id可能还没有在那里设置。
答案 1 :(得分:2)
pt_thread()
将在调用pthread_create()
后的某个任意点开始执行 - 包括它可能在pthread_create()
返回调用代码之前开始运行。并且无法保证pthread_create()
实现将在线程开始执行之前更新tid
变量。
因此,您的代码中没有任何内容可确保pt_routine()
正确读取tid
值。您需要使用某种同步来确保在没有数据争用的情况下正确发生。或者你可以让线程调用pthread_self()
。
请参阅the POSIX spec for pthread_create()
的“应用程序使用情况”部分:
在新创建的线程开始执行之前,对实现没有要求创建的线程的ID可用。调用线程可以通过pthread_create()函数的返回值获取创建的线程的ID,新创建的线程可以通过调用
pthread_self
获取其ID