3

I am getting back into using pthreads and the definition of pthread_join bothers me.

It says

"The pthread_join() function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already terminated. On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit() by the terminating thread shall be made available in the location referenced by value_ptr. When a pthread_join() returns successfully, the target thread has been terminated. The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined. If the thread calling pthread_join() is canceled, then the target thread shall not be detached."

I am trying to understand how, if I call pthread_join for one thread, then call pthread_join to start a second thread, the two threads are started, even though I imagine, the second pthread_join cannot be called because the first join has suspended the main thread from executing, and running the next line until pthread_exit is called from within the thread joined.

In particular, I imagine, the first pthread_join must wait until the specified thread has called pthread_exit, only then it should continue. However this is not the case, as I can do:

#include <pthread.h>
#include <stdio.h>

int avail = 0;

void *consumer(void *unused)
{
    while (1) {
        if (avail > 0) {
            --avail;
            puts("consumed");
        }
    }
}

void *producer(void *unused)
{
    while (1) {
        ++avail;
        puts("produced");
    }
}

int main(int argc, char **argv)
{
    pthread_t c_thread;
    pthread_t p_thread; 
    pthread_create(&c_thread, 0, consumer, 0);
    pthread_create(&p_thread, 0, producer, 0);
    pthread_join(c_thread, 0);
    pthread_join(p_thread, 0);

    return 0;
}

ignoring the problem of possible race conditions to try to reduce code size, why are both the threads working, despite the first join suspending the main thread (thus, preventing the next join from being called, in my mind).

I would really like to understand how this works.

Thanks ahead of time.

4
  • 2
    "I call pthread_join for one thread, then call pthread_join to create a second thread" -- pthread_join() doesn't create threads. That said, your "question" lacks a precise description of what you see and what you expect to see instead. Note also that your interpretation of what you saw is less important than what you actually saw. Commented Mar 13, 2015 at 18:48
  • 1
    You could add a sleep call or a call to scanf() waiting for input or set a breakpoint. The scheduler doesn't immediately switch to a different thread after it is created. That said, you could easily check if the second pthread_join() is called, or at least if the first one returns. Commented Mar 13, 2015 at 18:59
  • Okay that makes sense, so the join basically acts as a non-busy wait for the thread to finish before the program is resumed. The threads are indeed created and started by pthread_create, but need time to actually run, as main will exit early if it is not told to wait for anything. Commented Mar 13, 2015 at 19:01
  • 1
    "...for the threads to finish." No, for the thread to finish, specifically the one you specified when invoking pthread_join. And the user-code of the thread in question doesn't have to directly invoke pthread_exit either. It can simply return something; (see bullets in this man page). Not necessarily important to you, but significant for C++ programmers. Commented Mar 13, 2015 at 19:09

2 Answers 2

5

Threads run concurrently, starting sometime during or after the call to pthread_create. Calling pthread_join has nothing to do with starting or running the thread, it simply waits until it exits. Both your threads have already been running and are still runnable at the point you enter and block on the first join and they will continue to run. The only thing blocked by the first join is your main thread.

Sign up to request clarification or add additional context in comments.

2 Comments

You're right, what I was seeing is that if i remove joins, program exits early because it is not waiting on any threads to finish at all. If I make a busy loop instead of the joins "while(1) {}", the threads run anyway. Thanks!
The program is terminated when main returns. (I believe the standard says returning from main is equivalent to a call to exit) This includes the termination of all threads. The threads may or may not have run at this time, that would depend on how the threads are scheduled to run which depends on your platform.
0

The threads do not start in pthread_join, but rather in pthread_create. I mislead myself into thinking pthread_join was used to actually start the thread, whereas it is a non-busy wait for the specific thread to return before the main thread continues it's execution, in my case, main returns before the threads get a chance to call the puts function.

The second pthread_join in my code is never actually called, because main is indeed suspended from the first pthread_join waiting on c_thread to return. The second join in this particular scenario is a "no operation" and the program never actually gets to it because consumer never actually returns.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.