pthread_cond_wait() waking up two threads at the same time
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).
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.
pthread_cond_signal
wakes up one (random) thread waiting on the cond
variable. If you want to wake up all threads waiting on this cond
variable use pthread_cond_broadcast
.