如果多个线程加入一个线程,为什么未定义?

时间:2019-09-10 14:57:44

标签: c linux multithreading pthreads

如果我有多个线程,并且我想等待一个线程完成,那么为什么根据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
}

为什么这种行为是不确定的,或者换句话说是不可能的?

3 个答案:

答案 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”状态之间没有明显的区别。