4

I am new to conditional variables and get deadlock if not using pthread_cond_broadcast().

#include <iostream>
#include <pthread.h>

pthread_mutex_t m_mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;

bool ready = false;

void* print_id (void *ptr )
{
    pthread_mutex_lock(&m_mut);
    while (!ready) pthread_cond_wait(&cv, &m_mut);
    int id = *((int*) ptr);
    std::cout << "thread " << id  << '\n';
    pthread_mutex_unlock(&m_mut);
    pthread_exit(0);
    return NULL;
}

condition is changed here!

void go() {
    pthread_mutex_lock(&m_mut);
    ready = true;
    pthread_mutex_unlock(&m_mut);
    pthread_cond_signal(&cv);
}

It can work if I change the last line of go() to pthread_cond_broadcast(&cv);

int main ()
{
    pthread_t threads[10];

    // spawn 10 threads:
    for (int i=0; i<10; i++)
        pthread_create(&threads[i], NULL, print_id, (void *) new int(i));

    go();

    for (int i=0; i<10; i++) pthread_join(threads[i], NULL);

    pthread_mutex_destroy(&m_mut);
    pthread_cond_destroy(&cv);

    return 0;
}

The expected answer (arbitrary order) is

thread 0

....

thread 9

However, on my machine (ubuntu), it prints nothing. Could anyone tell me the reason? Thanks.

luyi0619
  • 313
  • 3
  • 8
  • Yes. _signal wakes up an arbitrary thread on the waiting list. Do I miss anything? – luyi0619 Jan 11 '15 at 15:49
  • _"However ... it prints nothing."_ Really? At first glance I'm dubious. Assuming stdout is line buffered (e.g., a terminal), I understand why the program might print anywhere from 1 to 10 lines of output, but not zero lines of output. If some threads are faster than `main`, as it were, at least one of them will be signaled and thus produce output. If some threads are slower than `main`, they'll find that `ready` is ready and also output a line each. – pilcrow Jan 12 '15 at 13:16

1 Answers1

1

From the manual page (with my emphasis):

pthread_cond_signal restarts one of the threads that are waiting on the condition variable cond. If no threads are waiting on cond, nothing happens. If several threads are waiting on cond, exactly one is restarted, but it is not specified which.

pthread_cond_broadcast restarts all the threads that are waiting on the condition variable cond. Nothing happens if no threads are waiting on cond.

Each of your ten threads is waiting on the same condition. You only call go() once - that's from main(). This calls pthread_cond_signal, which will only signal one of the threads (an arbitrary one). All the others will still be waiting, and hence the pthread_join hangs as they won't terminate. When you switch it to pthread_cond_broadcast, all of the threads are triggered.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • In my code, a thread must acquire a mutex before it can wait on the condition variable. I thought only one thread can wait on `cv`, am i right? – luyi0619 Jan 11 '15 at 15:47
  • Yes. `pthread_cond_wait` requires the mutex is locked on entry and automatically unlocks it, relocking it on exit. – abligh Jan 11 '15 at 15:48
  • Hmm, I still do not understand why it prints nothing. Do the ten threads wait on the `cv`? If they do, why I cannot use _signal? – luyi0619 Jan 11 '15 at 15:52
  • I can't tell you whether all ten threads wait on `cv`, because you haven't shown all the code, but I can only presume that's what's happening. If they all call `print_id` then yes they do. If so, `pthread_cond_signal` is not going to work as it is going to trigger one of the waiting threads at random, and you are only calling `go()` once, so only one will be triggered. – abligh Jan 11 '15 at 15:55
  • Actually yes, you've shown enough code to show that's absolutely the problem. I will amend my answer. – abligh Jan 11 '15 at 15:56