I have two threads and one CPU.
I want each of the two threads that reached line A earlier in their program to wait for the other thread to reach line A, after which both threads continue to run their program. I have done this as follows, But I want both threads of line A to run their program exactly at the same time.
How can I accomplish this?
My code:
//headers
static volatile bool waitFlag[2];
void *threadZero(void*){
//some codes
waitFlag[1] = true;
while(!waitFlag[0]);
//line A of thread zero
//some codes
}
void *threadOne(void*){
// some codes
waitFlag[0] = true;
while(!waitFlag[1]);
//line A of thread one
//some codes
}
int main(){
waitFlag[0] = waitFlag[1] = false;
//Creates two threads and waits for them to finish.
}
CodePudding user response:
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.
- If the counter is
- 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;
}