clinuxmultithreadingposixconditional-variable

How pritnOdd thread is able to proceed in below program to print natural numbers by even and odd threads?


Below programs works fine. But My doubt is very beginning both threads (printEven and printOdd) is waiting for signal on conditional variable( statement pthread_cond_wait(&cond, &mutex);) then how printOdd is able to proceed further even though printEven is not able so singal at that time.

I will put it in a simple way how the number 1 is getting printed ? Can anyone please help I am literally stuck with this for long time.

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

pthread_t       tid[2];
pthread_mutex_t mutex;
pthread_cond_t  cond;

int count = 1; // Shared variable to keep track of the current number to be printed

void* printEven(void* arg) {
    while (count <= 10) {
        pthread_mutex_lock(&mutex);
        while (count % 2 != 0) {
            printf("waiting for cv signal\n");
            pthread_cond_wait(&cond, &mutex);
        }
        printf("Even: %d\n", count++);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

void* printOdd(void* arg) {
    while (count <= 10) {
        pthread_mutex_lock(&mutex);
        while (count % 2 != 1) {
            pthread_cond_wait(&cond, &mutex);
        }
        printf("Odd: %d\n", count++);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

int main() {

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_create(&tid[1], NULL, printOdd, NULL);
    sleep(10);
    printf("creating even thread\n ");
    pthread_create(&tid[0], NULL, printEven, NULL);

    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

Solution

  • The number 1 gets printed because you are using pthread_cond_wait in exactly the way it is meant to be used. When printOdd is first called, count equals 1, so count%2 equals 1, so the function does not call pthread_cond_wait.

    In general, the right way to use pthread_cond_wait is,

        pthread_mutex_lock(&mutex);
        while (theNecessaryConditionIsNotYetMet()) {
            pthread_mutex_wait(&cond, &mutex);
        }
        doSomethingThatRequiresTheConditionToBeMet();
        pthread_mutex_unlock(&mutex);
    

    And, the whole point of locking the mutex is that no thread should ever change whether or not the condition is met except while it has the mutex locked.