3

I'm fairly new to threads in C. For this program I need to declare a thread which I pass in a for loop thats meant to print out the printfs from the thread.

I can't seem to get it to print in correct order. Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 16

void *thread(void *thread_id) {
    int id = *((int *) thread_id);
    printf("Hello from thread %d\n", id);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    for (int i = 0; i < NUM_THREADS; i++) {
        int code = pthread_create(&threads[i], NULL, thread, &i);

        if (code != 0) {
            fprintf(stderr, "pthread_create failed!\n");
            return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}

//gcc -o main main.c -lpthread
John Livingston
  • 43
  • 1
  • 11
  • That is a wrong expectation to have. Thread startup/execution sequence isn't required to be the same as the creation sequence. – work.bin Sep 30 '16 at 19:50
  • this is a good `pthread` tutorial: https://computing.llnl.gov/tutorials/pthreads/ – yano Sep 30 '16 at 20:59
  • Possible duplicate of [pthread execution on linux](https://stackoverflow.com/questions/4991470/pthread-execution-on-linux), [Pthread Run a thread right after it's creation](https://stackoverflow.com/q/12536649/608639), etc. – jww Aug 14 '19 at 12:52

1 Answers1

3

That's the classic example of understanding multi-threading. The threads are running concurrently, scheduled by OS scheduler. There is no such thing as "correct order" when we are talking about running in parallel.

Also, there is such thing as buffers flushing for stdout output. Means, when you "printf" something, it is not promised it will happen immediately, but after reaching some buffer limit/timeout.

Also, if you want to do the work in the "correct order", means wait until the first thread finishes it's work before staring next one, consider using "join": http://man7.org/linux/man-pages/man3/pthread_join.3.html

UPD: passing pointer to thread_id is also incorrect in this case, as a thread may print id that doesn't belong to him (thanks Kevin)

Eric Abramov
  • 462
  • 4
  • 19
  • So then its fine that its printing out in random order? I was assuming there was something wrong with the 'i' value that I was passing in the parameter of the function. – John Livingston Sep 30 '16 at 19:52
  • Yes, this will be the usual behaviour in your case. Try using "join" technique if you wish (this won't be parallel anymore) – Eric Abramov Sep 30 '16 at 19:53
  • I added "(void) pthread_join(threads[i], NULL);" after "int code =..." and it worked! thanks a bunch Eric. – John Livingston Sep 30 '16 at 19:59
  • 1
    Note that your threads all have a pointer to the same `int`. It's possible that if you don't use `join` you'll get multiple threads printing out the same id value. – Kevin Sep 30 '16 at 20:04
  • Kevin is correct, you may consider passing i by value, this may also be the reason for seeing "wrong order" (assuming earlier launched thread prints before next thread launches, which is not promised as well without join) – Eric Abramov Sep 30 '16 at 20:06
  • Why not use semaphores or mutex locks to ensure one thread can be inside the thread function at once. – Omid CompSCI Sep 30 '16 at 20:26
  • @JohnLivingston Just a note on practicality.. adding a `join()` statement in the `for` loop makes your threading utterly useless here. The whole point of threading is to parallelize execution. By spawning one thread, waiting for it finish, spawning the next, waiting for it to finish, etc,, you have absolutely no parallelization. In fact this will cause your code to run slower than a single-threaded app due to the overhead for creating/cleaning up threads. I know this is `hello world` for `pthreads`, but the rule of thumb is do NOT use threads just for fun. – yano Sep 30 '16 at 21:09
  • Thank you for the advice. I'll keep that in mind but as you said, it is just an introduction to pthreads so the point of the exercise I'm doing is to get the threads to print out one after the other. Stupid, I know, but the aim is for us to get an understanding of how joins work. Others suggested mutex and semaphores but we haven't gotten that far yet. – John Livingston Oct 03 '16 at 12:02