如果我有多个线程,并且我想等待一个线程完成,那么为什么根据pthread_join()函数未定义此线程?
例如,下面的代码显示线程1和2等待线程0:
void* thread1(void* t1){
..
pthread_join(pthread_t thread0, void **retval1);
return NULL
}
void* thread2(void* t2){
..
pthread_join(pthread_t thread0, void **retval2);
return NULL
}
为什么这种行为是不确定的,或者换句话说是不可能的?
答案 0 :(得分:3)
pthread_
t对象通常将指向一些与线程有关的已分配数据。这些数据通常是线程的返回值。 pthread_join
将读取返回值并释放线程数据。
如果您两次pthread_join
相同的pthread id,则可能会出现双精度的情况。指向的数据在第二次连接上可能无效,但也可能被另一个线程以不可预测的方式重用。
难以/无法推断结果。因此,UB。
答案 1 :(得分:1)
基本上,存储retval
中的thread0
,直到一个线程调用pthread_join
。之后,retval
将不再可用。
C ++具有std::shared_future
的明确设计,因此多个线程可以等待单个结果,这表明您的想法并不奇怪。
答案 2 :(得分:1)
pthread_join
是一种释放资源标识符的操作,例如文件描述符上的close
,分配的内存上的free
,文件名上的unlink
等。所有这些操作都是如果标识符(此处是构成pthread_t
值的特定位模式)将来可以再次使用,则固有地会遭受“两次释放” /“释放后使用”的错误。因此,该行为必须完全未定义,或者受使其成为严重编程错误的条件的限制,以至于可能无法定义。
请注意,在您的思维模型中,您可能会想到两个pthread_join
调用“在线程退出之前开始”,因此在pthread_t
标识符仍然有效的时间内发生。但是在形式上它们之间没有顺序,也没有顺序。在“已被pthread_join
阻塞”和“即将呼叫pthread_join
”状态之间没有明显的区别。