As you have noticed, thread 1 might signal the condition variable before thread 2 calls pthread_cond_wait()
. The condition variable does not "remember" that it has been signaled, so the wakeup will be lost. Therefore, you need to use some kind of variable to determine whether thread 2 needs to wait.
int signalled = 0;
void *thread_func1(void* arg){
printf("thread1 started
");
pthread_mutex_lock(&mutex);
printf("thread1: signalling
");
signalled = 1;
pthread_cond_signal(&cond);
printf("thread1: signalled
");
pthread_mutex_unlock(&mutex);
printf("thread1: exiting
");
pthread_exit(0);
}
void *thread_func2(void* arg){
printf("thread2 started
");
pthread_mutex_lock(&mutex);
printf("thread2: waiting for signal..
");
if(!signalled) {
pthread_cond_wait(&cond, &mutex);
}
printf("thread2: signal received
");
pthread_mutex_unlock(&mutex);
printf("thread2: exiting
");
pthread_exit(0);
}
However, this code is still not correct. The pthreads spec states that "spurious wakeups" may occur on condition variables. This means that pthread_cond_wait()
might return even if nobody has called pthread_cond_signal()
or pthread_cond_broadcast()
. Therefore, you need to check the flag in a loop, rather than just once:
void *thread_func2(void* arg){
printf("thread2 started
");
pthread_mutex_lock(&mutex);
printf("thread2: waiting for signal..
");
while(!signalled) {
pthread_cond_wait(&cond, &mutex);
}
printf("thread2: signal received
");
pthread_mutex_unlock(&mutex);
printf("thread2: exiting
");
pthread_exit(0);
}
Update: An alternate method to combine the function of a condition variable and a counter is to use a semaphore.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t sem;
void *thread_func1(void* arg){
printf("thread1 started
");
printf("thread1: signalling
");
sem_post(&sem);
printf("thread1: signalled
");
printf("thread1: exiting
");
pthread_exit(0);
}
void *thread_func2(void* arg){
printf("thread2 started
");
printf("thread2: waiting for signal..
");
sem_wait(&sem);
printf("thread2: signal received
");
printf("thread2: exiting
");
pthread_exit(0);
}
int main(int argc, char** argv){
pthread_t thread1, thread2;
sem_init(&sem);
pthread_create(&thread1, NULL, thread_func1, NULL);
pthread_create(&thread2, NULL, thread_func2, NULL);
pthread_join(thread1, 0);
pthread_join(thread2, 0);
sem_destroy(&sem);
return 0;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…