[英]When does the routine passed to pthread_create start?
Given the following code 给出以下代码
#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;
}
Can the routine ALWAYS get the right tid
? 常规总能得到正确的tid
?
Of course I could use pthread to fetch self ID but I just wonder when does the routine run. 当然,我可以使用pthread来获取自身ID,但是我只是想知道例程何时运行。
Well, there are actually 2 questions: 好吧,实际上有两个问题:
This answer concerns Linux, as I don't have any other platforms available. 这个答案与Linux有关,因为我没有其他可用的平台。 The answer to the first question can be found in the manuals : 第一个问题的答案可以在手册中找到:
Unless real-time scheduling policies are being employed, after a call to
pthread_create()
, it is indeterminate which thread—the caller or the new thread—will next execute. 除非采用实时调度策略,否则在调用pthread_create()
,不确定哪个线程(调用者或新线程)接下来将执行。
So it is clear that in your case, it is indeterminate which thread will actually run first. 因此很明显,在您的情况下,不确定哪个线程将首先运行。 Now, another question is how is pthread_create
implemented - if it could somehow create a dormant thread, storing its id first, and then later starting it? 现在,另一个问题是如何实现pthread_create
如果它可以以某种方式创建一个休眠线程,先存储其ID,然后再启动它?
Well, linux creates the new thread using the clone
system call: 好吧,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
Now, it seems that the thread id is stored with a pointer from the clone
call, but it seems clear that child_tidptr
doesn't refer to the address of tid
, as if I print it, the the address is different; 现在,似乎线程ID是与clone
调用中的指针一起存储的,但显然child_tidptr
并没有引用tid
的地址 ,就像我打印它一样,该地址是不同的。 this is some internal variable within the pthread
library; 这是pthread
库中的一些内部变量; and tid
would be updated after the clone
system call returns in the parent thread. clone
系统调用在父线程中返回后 , tid
将被更新。
And indeed, pthread_self
says the following: 实际上, pthread_self
表示以下内容:
The thread ID returned by
pthread_self()
is not the same thing as the kernel thread ID returned by a call togettid(2)
.pthread_self()
返回的线程ID与对gettid(2)
的调用返回的内核线程ID不同。
This confirms that the kernel thread ids are distinct from pthread_t
s 这确认内核线程ID与pthread_t
不同
Thus, in addition to this not being supported by the POSIX spec , there is no such guarantee on the Linux platform in practice - the tid
will need to be set in the parent thread after clone
returns, otherwise the parent wouldn't immediately know the thread id of the child - but this also means that if the child is the first to execute after the return, then the thread id might not be set there yet. 因此,除了POSIX规范不支持此功能外,实际上在Linux平台上也没有这样的保证- clone
返回后,需要在父线程中设置tid
,否则父级不会立即知道子代的线程ID-但这也意味着,如果子代是返回后第一个执行的子代,则可能尚未在此处设置线程ID。
pt_thread()
will begin execution at some arbitrary point after pthread_create()
is called - and that includes that it might start running before pthread_create()
returns to the calling code. pt_thread()
将在调用pthread_create()
之后的任意点开始执行-包括可能在pthread_create()
返回调用代码之前开始运行。 And there is no guarantee made that the pthread_create()
implementation will update the tid
variable before the thread starts execution. 并且不能保证pthread_create()
实现将在线程开始执行之前更新tid
变量。
So there is nothing in your code that ensures that pt_routine()
will read the tid
value properly. 因此,您的代码中没有什么可以确保pt_routine()
可以正确读取tid
值。 You would need to use some sort of synchronization to ensure that occurs properly without a data race. 您将需要使用某种同步来确保在没有数据争用的情况下正确进行。 Or you could have the thread call pthread_self()
. 或者,您可以使用线程调用pthread_self()
。
See the "Application Usage" section of the POSIX spec for pthread_create()
: 请参阅POSIX规范的“应用程序使用情况”部分中的pthread_create()
:
There is no requirement on the implementation that the ID of the created thread be available before the newly created thread starts executing. 在实现上,不需要在新创建的线程开始执行之前可用已创建线程的ID。 The calling thread can obtain the ID of the created thread through the return value of the pthread_create() function, and the newly created thread can obtain its ID by a call to
pthread_self
调用线程可以通过pthread_create()函数的返回值获取创建的线程的ID,而新创建的线程可以通过调用pthread_self
来获取其ID。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.