If you need to wait for thread to complete, but do not care about accuracy, merely a signal (one thread waits for another), then volatile, when compiled on modern compilers, should be enough.
If you have multiple threads, with one thread waiting on one/many of them, using semaphore is recommended.
Under Windows, you have WaitFor***Object(s) that does this.
However: waiting and threads are generally counter-productive. Optimal way is to use asynchronous approach, when a thread completes, it fires a callback or event, which does the next part of code.
Pseudo-code:
void foo() { // do lots of foo async(bar());}void bar() { // do just some of bar async(foo());};
Here you end up with infinite loop, whenever one function is complete, it will call next function asynchronously (via message, or some other inter-thread communication mechanism).