-1

I'm very new to thread coding, so I was doing an exercise I found out there on the web, which asks for something like this:

Write a program hellomany.c that will create a number N of threads specified in the command line, each of which prints out a hello message and its own thread ID. To see how the execution of the threads interleaves, make the main thread sleep for 1 second for every 4 or 5 threads it creates. The output of your code should be similar to:

   I am thread 1. Created new thread (4) in iteration 0...
   Hello from thread 4 - I was created in iteration 0
   I am thread 1. Created new thread (6) in iteration 1...
   I am thread 1. Created new thread (7) in iteration 2...
   I am thread 1. Created new thread (8) in iteration 3...
   I am thread 1. Created new thread (9) in iteration 4...
   I am thread 1. Created new thread (10) in iteration 5...
   Hello from thread 6 - I was created in iteration 1
   Hello from thread 7 - I was created in iteration 2
   Hello from thread 8 - I was created in iteration 3
   Hello from thread 9 - I was created in iteration 4
   Hello from thread 10 - I was created in iteration 5
   I am thread 1. Created new thread (11) in iteration 6...
   I am thread 1. Created new thread (12) in iteration 7...
   Hello from thread 11 - I was created in iteration 6
   Hello from thread 12 - I was created in iteration 7

What I've managed to code is this:

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

void* PrintHello(int iteration)
{
    printf("Hello from thread %u - I was created in iteration %d \n", 
    pthread_self(), iteration);
    pthread_exit(NULL);                 
}

int main(void)
{
    int        rc;                
    pthread_t  thread_id;             
    int        tidMain;
    int        n, i;

    tidMain = pthread_self();

    printf("How many threads are there to be created?\n");
    scanf("%d", &n);

    for(i = 1; i <= n; i++) {

        pthread_t thread_id;
        rc = pthread_create(&thread_id, NULL, PrintHello, i);
        printf("I am thread %u. Created new thread (%u) in iteration %d\n", 
        tidMain, thread_id, i);
        if(rc)                             
        {
            printf("\n ERROR: return code from pthread_create is %d \n", rc);
            exit(1);
        }
        if((i % 5) == 0) {
            sleep(1);
        }

    }

    pthread_exit(NULL);
}

The program does really print what I want to, and even sleeps and "breaks" the creation each 5 threads created; still, I don't know why, but when each created thread gets to be executed (after main thread has informed they have been created) in the 5-thread-printing-streak i want to, first thread that "greets" is the last created one. What i get from the console, i.e. when I ask it to create 8 threads, is this:

I am thread 3075630848. Created new thread (3075627840) in iteration 1
I am thread 3075630848. Created new thread (3067235136) in iteration 2
I am thread 3075630848. Created new thread (3058842432) in iteration 3
I am thread 3075630848. Created new thread (3050449728) in iteration 4
I am thread 3075630848. Created new thread (3042057024) in iteration 5
Hello from thread 3042057024 - I was created in iteration 5 
Hello from thread 3050449728 - I was created in iteration 4 
Hello from thread 3058842432 - I was created in iteration 3 
Hello from thread 3067235136 - I was created in iteration 2 
Hello from thread 3075627840 - I was created in iteration 1 
I am thread 3075630848. Created new thread (3032480576) in iteration 6
I am thread 3075630848. Created new thread (3024087872) in iteration 7
I am thread 3075630848. Created new thread (3015695168) in iteration 8
Hello from thread 3015695168 - I was created in iteration 8 
Hello from thread 3024087872 - I was created in iteration 7 
Hello from thread 3032480576 - I was created in iteration 6

As long as I understand, it is first executing the last thread created. Why does this happen? Can I get it to execute the first created one first?

BTW: I'm running on Ubuntu

jww
  • 97,681
  • 90
  • 411
  • 885
gciavirella
  • 41
  • 1
  • 2
  • 5
  • 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:51

3 Answers3

1

This is the point about concurrent programming. You can never make any assumptions about the order in which the threads execute. I, for example get the following output:

I am thread 639280960. Created new thread (630781696) in iteration 1
Hello from thread 630781696 - I was created in iteration 1
I am thread 639280960. Created new thread (622388992) in iteration 2
Hello from thread 622388992 - I was created in iteration 2
I am thread 639280960. Created new thread (613996288) in iteration 3
Hello from thread 613996288 - I was created in iteration 3
I am thread 639280960. Created new thread (536868608) in iteration 4
Hello from thread 536868608 - I was created in iteration 4
I am thread 639280960. Created new thread (526280448) in iteration 5
Hello from thread 526280448 - I was created in iteration 5
I am thread 639280960. Created new thread (517887744) in iteration 6
I am thread 639280960. Created new thread (509495040) in iteration 7
Hello from thread 509495040 - I was created in iteration 7
I am thread 639280960. Created new thread (501102336) in iteration 8
Hello from thread 501102336 - I was created in iteration 8
Hello from thread 517887744 - I was created in iteration 6

If I run it again, I might get a different output. Try it out on your own!

The Wikipedia Article about Concurrent computing, says the following:

The exact timing of when tasks in a concurrent system are executed depend on the scheduling, and tasks need not always be executed concurrently. For example, given two tasks, T1 and T2:

  • T1 may be executed and finished before T2 or vice versa (serial and sequential)

  • T1 and T2 may be executed alternately (serial and concurrent)

  • T1 and T2 may be executed simultaneously at the same instant of time (parallel and concurrent)

I suggest, you read some basic articles or literature about concurrency and parallelism.

Community
  • 1
  • 1
p0wl
  • 658
  • 5
  • 10
  • 1
    I see! Thank you, i knew they were kind of not-deterministic, but it kinda stranged me that the execution order was mostly like a stack. Guess its a matter of randomness – gciavirella Jul 19 '18 at 19:12
1

It's a concurrent program. If you run your program several times, the order may be different even in the same host.

By the way, maybe it is better for you to see pthread API first before coding.

For pthread_create():

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

The 3rd argument is void *(*start_routine)(void *) rather than void *(start_routine)(int), and the 4th argument is void * rather than int.

Joy Allen
  • 402
  • 3
  • 8
1

The order in which threads are executed is undetermined. If you need a specific order than you have to use locks, mutexes and conditions to order their executuion to your requirements.

The order that you see is caused by your hardware and kernel and sometimes randomness. I'm assuming you have a single core cpu or the output would make little sense. When you create a thread your kernel simply schedules the thread to run at a later time and keeps executing the main thread. So you get messages for all 5 thread creations. Only when the main thread sleeps the kernel switches to the next thread ready to run. It seems to do this as FILO (first in - last out). That just happens to be what your kernel in your version on your hardware happens to do. Could change at any moment.

pOwl on the other hand seems to have multiple cores. So while the main thread creates thread the other core(s) already execute them. Or he simply has a different kernel.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42