虚假唤醒后的互斥状态

考虑使用pthreads这个基本的multithreading程序。 我们有一个主线程,创建另一个做一些工作的线程。

bool done = false; mutex m; condition c; void foo() { pthread_mutex_lock(&m); //while(!done) { pthread_cond_wait(&c, &m); // Spuriously wakeup while child is doing work. // child thread has NOT unlocked the mutex yet // Do I now own the mutex? // or am I waiting for child to unlock it? //} pthread_mutex_unlock(&m); } void * child(void *arg) { pthread_mutex_lock(&m); some_intense_work(); // this work is done while mutex is held! // the main thread spuriously wakes up // while this work is being done // (while this child thread is holding the mutex) done = true; pthread_cond_broadcast(&c); pthread_mutex_unlock(&m); } int main(int argc, char *argv[]) { pthread_t p; pthread_create(&p, NULL, child, NULL); foo(); } 

假设我们实现了一个没有周围的while子句检查谓词的等待,即使我们知道没有人应该这样做。

现在,如果在子线程正在执行其工作时,主线程中发生虚假唤醒,互斥锁m的状态是什么? 主线程是否会在没有孩子首先解锁的情况下拥有它,这样两者都拥有它?

或者,虚假的唤醒是否只是跳过等待条件,而不是等待释放互斥锁?

当某个其他线程持有相关的互斥锁时, pthread_cond_wait()调用不能“虚假地”唤醒。 当pthread_cond_wait()成功返回时,它将声明互斥锁,因此在互斥锁可用之前无法成功返回。

在您的示例中,可能会发生虚假唤醒,因为foo()可以调用pthread_cond_wait()并且在child()有机会首先调用pthread_mutex_lock()之前发生虚假唤醒。

您的示例中的另一个问题(禁用注释代码)的原因是pthread_cond_wait()调用永远不会被唤醒。 如果child()foo()设法获取互斥锁之前完成所有处理,则会发生这种情况。 在那种情况下, child()将在主线程在pthread_cond_wait()等待之前调用pthread_cond_broadcast() ,因此主线程将错过广播。 由于foo()在持有互斥锁时从不检查done ,因此它不会注意到child()已完成其工作。

这就是为什么pthread_cond_wait()几乎总是必须在检查条件的循环中执行。