在调用pthread_create(&id,NULL,&start_routine,arg)中,是否保证在start_routine开始运行之前将线程ID写入id?这些联机帮助页很清楚start_routine可能但不一定会在调用pthread_create之前开始执行,但是当线程id被写回传递的thread参数时它们是静默的 .
我的具体情况是我有一个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);
}
}
这种重写在实践中要稳定得多,但它实际上是一个修复还是只是一个较小的竞争条件窗口?
2 回答
线程id肯定是在
pthread_create
返回之前写的 . 如果你考虑一下,pthread_create
就不可能以任何其他方式工作 . 它无法委托将线程id写入新线程,因为pthread_t
变量可能在新线程运行时超出范围 .相关文字是:
(来自http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html)请注意,它表示函数的"on successful completion",而不是"at an indeterminate time after successful completion" .
更有趣的问题,我在这一点上不清楚的是,在新线程启动函数开始之前,
pthread_create
是否必须完成将线程id写入其目的地,即新线程是否可以立即看到其自己的线程ID,例如,如果要存储在全局变量中 . 我怀疑答案是否定的 .Edit: 在重新阅读你的问题后,似乎你可能真的一直在询问后一个更有趣的问题 . 在任何情况下,都有's no reason for the new thread'的启动函数来使用
pthread_create
写出的thread-id . 您的新线程可以(并且应该)使用pthread_self
来获取自己的线程ID .我相信规范中没有任何内容要求pthread_create在
start_routine
中的代码开始执行之前分配其输出参数pthread_t *thread
.作为一个实际问题,以下程序在许多pthreads实现(freebsd8 i386和debian gnu / linux amd64)上成功,但对我感兴趣的是失败(debian / kfreebsd9 amd64):
那就是说,我不确定我是否理解这个行为细节如何与您在原始问题中提供的两种代码替代相关 . 虽然我发现如果pthread_create在执行期间将其他值写入
*thread
,并且您在另一个线程中使用了*id
的值,那么它可能是相关的 . 该标准未指定在成功执行pthread_create期间没有其他'intermediate'值写入*thread
.