Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pthread_cond_wait() waking up two threads at the same time

I am trying to better understand how to use pthread_cond_wait() and how it works. I am just looking for a bit of clarification to an answer I saw on this site.

The answer is the last reply on this page

understanding of pthread_cond_wait() and pthread_cond_signal()

I am wondering how this would look with three threads. Imagine Thread 1 wants to tell Thread 2 and Thread 3 to wake up

For example

pthread_mutex_t mutex;
pthread_cond_t condition;

Thread 1:

pthread_mutex_lock(&mutex);

/*Initialize things*/

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 2 & 3

/*Do other things*/

Thread 2:

pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
    pthread_cond_wait(&condition, &mutex); //wait for the condition
}
pthread_mutex_unlock(&mutex);

/*Do work*/

Thread 3:

pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
    pthread_cond_wait(&condition, &mutex); //wait for the condition
}
pthread_mutex_unlock(&mutex);

/*Do work*/

I am wondering if such a setup is valid. Say that Thread 2 and 3 relied on some intialization options that thread 1 needs to process.

like image 302
user2327195 Avatar asked Jul 15 '15 21:07

user2327195


2 Answers

First: If you wish thread #1 to wake up thread #2 and #3, it should use pthread_cond_broadcast.

Second: The setup is valid (with broadcast). Thread #2 and #3 are scheduled for wakeup and they will try to reacquire the mutex as part of waking up. One of them will, the other will have to wait for the mutex to be unlocked again. So thread #2 and #3 access the critical section sequentically (to re-evaluate the condition).

like image 73
Laurent Michel Avatar answered Oct 19 '22 14:10

Laurent Michel


If I understand correctly, you want thr#2 and thr#3 ("workers") to block until thr#1 ("boss") has performed some initialization.

Your approach is almost workable, but you need to broadcast rather than signal, and are missing a predicate variable separate from your condition variable. (In the question you reference, the predicate and condition variables were very similarly named.) For example:

pthread_mutex_t mtx;
pthread_cond_t  cv;
int             initialized = 0;  // our predicate of interest, signaled via cv

...

// boss thread
  initialize_things();
  pthread_mutex_lock(&mtx);
  initialized = 1;
  pthread_cond_broadcast(&cv);
  pthread_mutex_unlock(&mtx);
  ...

// worker threads
  pthread_mutex_lock(&mtx);
  while (! initialized) {
    pthread_cond_wait(&cv, &mtx);
  }
  pthread_mutex_unlock(&mtx);
  do_things();

That's common enough that you might want to combine the mutex/cv/flag into a single abstraction. (For inspiration, see Python's Event object.) POSIX barriers which are another way of synchronizing threads: every thread waits until all threads have "arrived." pthread_once is another way, as it runs a function once and only once no matter how many threads call it.

like image 5
pilcrow Avatar answered Oct 19 '22 14:10

pilcrow