A busy loop is inefficient for this purpose. What you want is a condition, a mutex and a simple counter:
- Lock the mutex.
- Increase the counter.
- If the counter is
2
, broadcast on the condition.
- Otherwise wait on the condition.
- Unlock the mutex.
This logic can be easily adapted to any number of threads by changing the threshold for the counter. The last thread to increment the counter (protected by the mutex) will broadcast on the condition and will unlock itself and all the other threads simultaneously. If you want to synchronize multiple times you can also reset the counter.
Here's an example:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/random.h>
pthread_cond_t cond;
pthread_mutex_t cond_mutex;
unsigned int waiting;
// Sleep a random amount between 0 and 3s.
// This is just for testing, you don't actually neeed it.
void waste_time(void) {
unsigned us;
getrandom(&us, sizeof(us), 0);
us %= 3000000;
fprintf(stderr, "[%lx] Sleeping %u us...\n", pthread_self(), us);
usleep(us);
}
void synchronize(void) {
pthread_mutex_lock(&cond_mutex);
if (++waiting == 2) {
pthread_cond_broadcast(&cond);
} else {
while (waiting != 2)
pthread_cond_wait(&cond, &cond_mutex);
}
pthread_mutex_unlock(&cond_mutex);
}
void *threadZero(void *_) {
waste_time();
// ...
synchronize();
fprintf(stderr, "[%lx] Resuming.\n", pthread_self());
// ...
return NULL;
}
void *threadOne(void *_) {
waste_time();
// ...
synchronize();
fprintf(stderr, "[%lx] Resuming.\n", pthread_self());
// ...
return NULL;
}
int main(void) {
pthread_t zero, one;
pthread_create(&zero, NULL, threadZero, NULL);
pthread_create(&one, NULL, threadOne, NULL);
// ...
pthread_join(zero, NULL);
pthread_join(one, NULL);
return 0;
}