考虑这个使用 pthread 的基本多线程程序。
我们有一个主线程,创建另一个执行一些工作的线程。
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 的状态将是什么?主线程是否会在子线程先解锁它的情况下拥有它,以便双方都拥有它?
或者虚假唤醒是否仅跳过对条件的等待,而不是对互斥体被释放的等待?
The pthread_cond_wait()
当其他线程持有关联的互斥锁时,调用无法“虚假”唤醒。什么时候pthread_cond_wait()
成功返回,它将声明该互斥锁,因此在互斥锁可用之前它无法成功返回。
在您的示例中,可能会发生虚假唤醒,因为foo()
可以打电话pthread_cond_wait()
并让虚假唤醒发生在child()
有机会打电话pthread_mutex_lock()
首先。
您的示例中的另一个问题(注释代码被禁用)是可能的pthread_cond_wait()
拨电至never唤醒。这种情况可能会发生,如果child()
之前完成所有处理foo()
设法获取互斥体。在那种情况下,child()
将会通知pthread_cond_broadcast()
在主线程等待之前pthread_cond_wait()
所以主线程会错过广播。自从foo()
从不检查done
当持有互斥体时,它不会注意到child()
已经完成了它的工作。
这就是为什么pthread_cond_wait()
几乎总是必须在检查条件的循环中执行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)