With POSIX threads, it is not possible for a thread to join(), or wait for the termination of, a non-specific thread; you have to identify the thread you’re waiting for. Yes, there is a rationale behind the absence of this feature.
Unix programmers are used to being able to call the wait() in such a way that it will return when any child process exits, but expecting this to work for threads can cause confusion. The important thing to note here is that Unix processes are based around a notion of parent and child; this is a notion that is not present in most threads systems. Since threads don’t have this notion, join()ing on “any” thread could have the undesirable effect of having a join() return once a completely unrelated thread happened to exit.
In many (perhaps even most) threaded applications, you do not want to be able to join() with an arbitrary thread in your process. Consider, for example, a library call that one of your threads might make, which in its turn might start a few threads and try to join() on them. If another of your threads, join()ing on “any” thread, happened to join() on one of the library call’s threads, that would lead to incorrect program behaviour.
If you want to be able to join() on any thread so that, for example, you can keep track of the number of running threads, you can achieve the same functionality by starting detached threads and having them decrememnt a (suitably locked, of course) counter as they exit.