pthreads: a thread that triggers other threads

c++, multithreading, pthreads, synchronization

Solution

Use of condition variables (DOESN'T WORK: in some case I get a deadlock):

The code doesn't lock the mutex when checking the state of shared variable `ready`. When it does lock the mutex `ready` may have well changed by that time, this is why you see deadlocks.

The correct version to wait for state change with a condition variable is (error checking omitted):

pthread_mutex_lock(&ready_mutex);
while(!ready) // Needed to avoid spuriuos wake-up
    pthread_cond_wait(&ready_cond, &ready_mutex);
// ready == true here
pthread_mutex_unlock(&ready_mutex);

The above assumes that `ready` is ever changed only when the same mutex is held.

Problem

Hello, I'm new to multi-thread programming. I'm trying to create a code that creates a thread THREAD1, that, after it has done something, it triggers two other threads, say THREAD2 and THREAD3, and then exits. I wrote two possible solutions. 1) Use of condition variables (DOESN'T WORK: in some case I get a deadlock): ``` pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER; bool ready = false; void* trigger(void*); void* func1(void*); void* func2(void*); int main() { pthread_t thread1; pthread_t thread2; pthread_t thread3; pthread_create(&thread1, 0, &trigger, 0); pthread_create(&thread2, 0, &func1, 0); pthread_create(&thread3, 0, &func2, 0); pthread_join(thread1, 0); pthread_join(thread2, 0); pthread_join(thread3, 0); } void *trigger(void*) { pthread_mutex_lock(&ready_mutex); ready = true; pthread_cond_broadcast(&ready_cond); pthread_mutex_unlock(&ready_mutex); return 0; } void *func1(void*) { while (!ready) // Needed to avoid spuriuos wake-up { pthread_mutex_lock(&ready_mutex); pthread_cond_wait(&ready_cond, &ready_mutex); pthread_mutex_unlock(&ready_mutex); } std::cout << "In 'func1'>> Do something" << std::endl; return 0; } void *func2(void*) { while (!ready) // Needed to avoid spuriuos wake-up { pthread_mutex_lock(&ready_mutex); pthread_cond_wait(&ready_cond, &ready_mutex); pthread_mutex_unlock(&ready_mutex); } std::cout << "In 'func2'>> Do something" << std::endl; return 0; } ``` 2) THREAD1 directly creates the two other threads. ``` pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER; pthread_t thread1; pthread_t thread2; pthread_t thread3; void* trigger(void*); void* func1(void*); void* func2(void*); int main() { pthread_create(&thread1, 0, &trigger, 0); pthread_join(thread1, 0); pthread_join(thread2, 0); pthread_join(thread3, 0); } void *trigger(void*) { std::cout << "In 'trigger'>> Do something" << std::endl; pthread_create(&thread2, 0, &func1, 0); pthread_create(&thread3, 0, &func2, 0); return 0; } void *func1(void*) { std::cout << "In 'func1'>> Do something" << std::endl; return 0; } void *func2(void*) { std::cout << "In 'func2'>> Do something" << std::endl; return 0; } ``` I would like to know your opinion. Thank you very much

Original source