pthread_create写回的时机
在调用pthread_create(&id, NULL, &start_routine, arg)中,线程id是否保证在start_routine开始运行之前写入id?联机帮助页清楚地表明,start_routine 可能但不一定会在对 pthread_create 的调用返回之前开始执行,但是当线程 id 写回传递的线程参数时,它们却保持沉默。
我的具体情况是,我有一个围绕 pthread_create: 的包装器,
int mk_thread(pthread_t *id) {
pthread_t tid;
pthread_create(&tid,NULL,ThreadStart,NULL);
if (id == NULL) {
pthread_detach(tid);
} else {
*id=lid;
}
}
它显然可以在写回之前运行启动例程。我将其更改为此
int mk_thread(pthread_t *id) {
pthread_t tid,tidPtr=id?id:&tid;
pthread_create(tidPtr,NULL,ThreadStart,NULL);
if (id == NULL) {
pthread_detach(tid);
}
}
重写在实践中更加稳定,但它实际上是修复还是只是竞争条件的较小窗口?
In the call pthread_create(&id, NULL, &start_routine, arg), is the thread id guaranteed to be written to id before start_routine starts running? The manpages are clear that the start_routine may but will not necessarily begin executing before the call to pthread_create returns, but they are silent on when the thread id gets written back to the passed thread argument.
My specific case is that I have a wrapper around pthread_create:
int mk_thread(pthread_t *id) {
pthread_t tid;
pthread_create(&tid,NULL,ThreadStart,NULL);
if (id == NULL) {
pthread_detach(tid);
} else {
*id=lid;
}
}
which can obviously run the start routine before writing back. I changed it to
int mk_thread(pthread_t *id) {
pthread_t tid,tidPtr=id?id:&tid;
pthread_create(tidPtr,NULL,ThreadStart,NULL);
if (id == NULL) {
pthread_detach(tid);
}
}
This rewrite is much more stable in practice, but is it actually a fix or just a smaller window for the race condition?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
线程 ID 肯定是在
pthread_create
返回之前写入的。如果您考虑一下,pthread_create
不可能以任何其他方式工作。它无法将线程 ID 的写入委托给新线程,因为在新线程运行时 pthread_t 变量可能超出范围。相关文字是:
(来自 http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create .html)请注意,它说的是函数的“成功完成时”,而不是“成功完成后的不确定时间”。
更有趣的问题,我对此不清楚,是 pthread_create 是否必须在新线程启动函数开始之前完成将线程 id 写入其目的地,即新线程是否可以立即看到它自己的线程ID,例如,如果它要存储在全局变量中。我怀疑答案是否定的。
编辑:重新阅读您的问题后,您似乎确实在问后一个更有趣的问题。无论如何,新线程的启动函数没有理由使用
pthread_create
写出的线程 ID。您的新线程可以(并且应该)只使用 pthread_self 来获取自己的线程 ID。The thread id is definitely written before
pthread_create
returns. If you think about it, it would be impossible forpthread_create
to work any other way. It could not delegate writing the thread id to the new thread, because thepthread_t
variable might be out of scope by the time the new thread runs.The relevant text is:
(From http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html) Note that it says "on successful completion" of the function, not "at an indeterminate time after successful completion".
The more interesting question, and I'm unclear on this one, is whether
pthread_create
must have finished writing the thread id to its destination before the new thread start function begins, i.e. whether the new thread can immediately see its own thread id, e.g. if it's to be stored in a global variable. I suspect the answer is no.Edit: Upon rereading your question, it seems like you might really have been asking about this latter, more interesting question. In any case, there's no reason for the new thread's start function to use the thread-id written out by
pthread_create
. Your new thread can (and should) just usepthread_self
to get its own thread id.我相信规范中没有任何内容要求 pthread_create 在
start_routine
中的代码开始执行之前分配其输出参数pthread_t *thread
。作为实用性问题,以下程序在许多 pthreads 实现(freebsd8 i386 和 debian gnu/linux amd64)上成功,但在我感兴趣的一个(debian/kfreebsd9 amd64)上失败:
也就是说,我不确定我是如何理解这一点的行为细节与您在原始问题中提供的两个代码替代方案相关。尽管我想到,如果 pthread_create 在执行期间向
*thread
写入其他值,并且您在其他线程中使用*id
的值,则可能是相关的。该标准没有指定在成功执行 pthread_create 期间不向 *thread 写入其他“中间”值。I believe that nothing in the spec requires pthread_create to assign its output parameter
pthread_t *thread
before code instart_routine
begins to execute.As a matter of practicality, the following program succeeds on many pthreads implementations (freebsd8 i386 and debian gnu/linux amd64) but fails on one of interest to me (debian/kfreebsd9 amd64):
that said, I am not sure I understand how this detail of behavior is relevant to the two code alternatives you offer in the original question. Though it occurs to me that if pthread_create writes other values to
*thread
during its execution, and you're using the value of*id
in the other thread, it could be relevant. The standard does not specify that no other 'intermediate' values are written to*thread
during successful execution of pthread_create.