I believe the technical reason is that pthread_join is a POSIX standard which, for multithreading, tries to specify only necessary primitives for implementers. Any richer semantics would introduce a costlier implementation and perhaps a more difficult API.
Indeed, POSIX already considers this function to be a convenience, rather than a primitive, in support of a very, very common use case: one thread waits for the termination of one other.
The first paragraph of the POSIX.1-2008 pthread_join RATIONALE is a bit lengthy, but makes many germane observations:
The pthread_join() function is a convenience that has proven useful in multi-threaded applications. It is true that a programmer could simulate this function if it were not provided by passing extra state as part of the argument to the start_routine(). The terminating thread would set a flag to indicate termination and broadcast a condition that is part of that state; a joining thread would wait on that condition variable. While such a technique would allow a thread to wait on more complex conditions (for example, waiting for multiple threads to terminate), waiting on individual thread termination is considered widely useful. Also, including the pthread_join() function in no way precludes a programmer from coding such complex waits. Thus, while not a primitive, including pthread_join() in this volume of POSIX.1-2008 was considered valuable.
pthread_join()
returns, the last resources associated with the exited thread are released. No otherpthread_join()
can touch that thread, because nothing of it remains. It has to be that way, how else would the pthread-library know when to release those resources? If multiple threads could join with one pthread, you'd have a permanent resource leak for every exited thread. – EOF