Introduction to Conditional Variables

This lesson presents the motivation to study conditional variables.

Thus far you have developed the notion of a lock and seen how one can be properly built with the right combination of hardware and OS support. Unfortunately, locks are not the only primitives that are needed to build concurrent programs.

In particular, there are many cases where a thread wishes to check whether a condition is true before continuing its execution. For example, a parent thread might wish to check whether a child thread has completed before continuing, this is often called a join(). How should such a wait be implemented? Let’s look at the code excerpt below:

Press + to interact
void *child(void *arg) {
printf("child\n");
// XXX how to indicate we are done?
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t p;
Pthread_create(&p, NULL, child, NULL); // create child
// XXX how to wait for child?
printf("parent: end\n");
return 0;
}

What we would like to see here is the following output:

parent: begin
child
parent: end

You could try using a shared variable, as shown in the code widget below. This solution will generally work, but it is hugely inefficient as the parent spins and wastes CPU time. What you would like here instead is some way to put the parent to sleep until the condition you are waiting for (e.g., the child is done executing) comes true.

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include "common.h"
#include "common_threads.h"

volatile int done = 0;

void *child(void *arg) {
    printf("child\n");
    sleep(5);
    done = 1;
    return NULL;
}

int main(int argc, char *argv[]) {
    pthread_t p;
    printf("parent: begin\n");
    Pthread_create(&p, NULL, child, NULL);
    while (done == 0) 
        ; // spin
    printf("parent: end\n");
    return 0;
}
Parent Waiting For Child: Spin-based Approach

THE CRUX: HOW TO WAIT FOR A CONDITION

In multi-threaded programs, it is often useful for a thread to wait for some condition to become true before proceeding. The simple approach, of just spinning until the condition becomes true, is grossly inefficient and wastes CPU cycles, and in some cases, can be incorrect. Thus, how should a thread wait for a condition?

Get hands-on with 1400+ tech skills courses.