Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

If pthread_cond_wait() requires locked mutex, doesn't it block the thread which changed condition?

I need a two-threaded application. One thread prepare data, one process it. If there is no data to process, the second thread should sleep. Doing as tons of tutorials suggests:

pthread_mutex_t mtx;
pthread_cond_t cond;

char *shared_data = NULL;

char *process_data() {
    char *dt;

    pthread_mutex_lock(&mtx);
    if(!shared_data) pthread_cond_wait(&cond, &mtx);

    dt = strdup(shared_data);
    free(shared_data);
    shared_data = NULL;

    pthread_mutex_unlock(&mtx);

    return dt;
}

void create_data(char *dt) {
    pthread_mutex_lock(&mtx);

    shared_data = strdup(dt);

    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mtx);
}

So, assuming the reader thread starts first.

  1. The shared_data is currently NULL and there is nothing to read. So it locks the mutex and waits till cond is triggered.
  2. The creator thread starts, it tries to lock the mutex, but it is already locked by the waiting reader…

Aren’t we in a deadlock? What am I missing here?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

In a simplified world, this is what happens:

pthread_mutex_lock(&mtx);

// the mutex is now locked so it's safe to access shared_data

if(!shared_data) // safe

    // now, unlock the mutex to let others lock it and when the condition
    // variable gets signalled, re-lock the mutex and return

    pthread_cond_wait(&cond, &mtx);

So, there’s no catch 22. The mutex is unlocked/relocked (sometimes multiple times) inside pthread_cond_wait. When pthread_cond_wait returns, it will be locked.

The most important part here that isn’t quite true is that pthread_cond_wait may actually return even before the condition variable is signalled. This is called spurious wakeups and happens for implementation specific reasons. The only way to be sure that what you are waiting for has actually happend is to check that the shared resource has actually changed into the state you are waiting for.

Simply replace if with while.

while(!shared_data)
    pthread_cond_wait(&cond, &mtx);

Not replacing the if with while in your case will eventually bite you and you’ll suddenly be using a NULL pointer in the following code.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading