Thomas
Thomas

Reputation: 315

C multithread program behaviour explanation

int g_ant = 0;
void *writeloop(void *arg)
 {
 while(g_ant < 10)
  {
  g_ant++;
  usleep(rand()%10);
  printf("%d\n", g_ant);
  }
 exit(0);
 }

int main(void)
 {
 pthread_t time;
 pthread_create(&time, NULL, writeloop, NULL);
 writeloop(NULL);
 pthread_join(time, NUL);
 return 0;
 }

Hi! I have four questions which I believe goes under the category race condition...? :-)

  1. I'm trying to figure out why the printf of g_ant, on my computer, starts on 2 and continues to 10 in 90% of the cases, with an occasional 1, 3->10 output. My guess is because of the usleep which may hinder thread1 long enough to let thread2 increment and printf before thread1 reaches printf.
  2. Wouldn't this also mess up numbers from 2->10?
  3. I'm also struggeling to understand pthread_join's function in this program. My understanding is that it's used to wait for a thread to complete. Is it waiting for the writeloop function started by pthread_create?
  4. Is writeloop(null) considered second thread?

Upvotes: 1

Views: 106

Answers (2)

John Estess
John Estess

Reputation: 636

  1. The main thread is considered another thread. The following might help you understand what's going on before you add mutexes (assuming you have to do that next). Usually, you don't exit() the whole process from a thread - it would never be joined in the main thread.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int g_ant = 0;

void *writeloop(void *arg)
{
    while(g_ant < 10)
    {
        g_ant++;
        usleep( rand() % 10 );
        printf("thread: %u global: %d\n", (unsigned int)pthread_self(), g_ant);
    }
    return NULL;
}

int main(void)
 {
    pthread_t t;
    pthread_create(&t, NULL, writeloop, NULL);
    writeloop(NULL);
    pthread_join(t, NULL);
    printf("Joined\n");
    return 0;
 }

Upvotes: 2

sammy-sc
sammy-sc

Reputation: 171

  1. g_ant++; isn't atomic operation, which can cause undefined behaviour. You should use
    pthread_mutex_lock(&mutex); and pthread_mutex_unlock(&mutex); the reason why it 90% times starts at 2 is because thread time enters the function, increments g_ant and sleeps itself. OS tends to take it away from CPU and put there another thread that is not asleep, in your case that is your main thread which again increments it by 1 runs usleep. Now g_ant has value 2, thread time resumes and prints 2 and increments it to 3. Main thread gets resumed and prints the 3 and again increments it, this keeps switching that's why you see numbers from 2 -> 10 most of the time.

Hopefully it is clear enough and should answer 2. question as well.

  1. pthread_join makes sure that other threads finish their job before your main thread quits the program.

  2. nope it is not considered a second thread, it runs the function on the main thread.

    hope it helps.

Upvotes: 3

Related Questions