关于这个: How To Use Condition Variable
假设我们有许多执行此类代码的消费者线程(从引用的页面复制):
while (TRUE) {
s = pthread_mutex_lock(&mtx);
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) { /* Consume all available units */
avail--;
}
s = pthread_mutex_unlock(&mtx);
}
我假设这里的场景是:主线程调用pthread_cond_signal()来告诉消费者线程做一些工作。
据我所知 - 后续线程调用pthread_mutex_lock()然后调用pthread_cond_wait()(以原子方式解锁互斥锁)。到目前为止,没有任何消费者线程声称使用互斥锁,它们都在pthread_cond_wait()上等待。
当主线程在manpage之后调用pthread_cond_signal()时,至少会唤醒一个线程。当其中任何一个从pthread_cond_wait()返回时,它会自动声明互斥锁。
所以我的问题是:现在关于提供的示例代码会发生什么? 即,失去互斥体竞赛的线程现在做了什么?
(AFAICT赢得互斥锁的线程,应该运行其余的代码并释放互斥锁。丢失的那个应该等待互斥锁 - 在第一个嵌套的某个地方 {{ 1}}循环 - 当胜利者持有它并且在它被释放之后开始阻止pthread_cond_wait()因为那时while
将被满足。我是否正确?)
答案 0 :(得分:6)
请注意,pthread_cond_signal()
通常只用于唤醒一个等待线程(这就是它保证的全部)。但它可能会“意外地”唤醒。 while (avail > 0)
循环执行两个函数:
它还可以防止在while (avail > 0)
完成之后但在工作线程再次等待条件之前工作单元可能已放入队列的竞争条件 - 但该竞争也由在调用if
之前进行pthread_cond_wait()
测试。
基本上当一个线程被唤醒时,它只知道可能是它要使用的工作单元,但可能没有(另一个线程可能已经消耗它们)。
因此调用pthread_cond_signal()
时发生的事件序列为:
while (avail > 0)
循环中执行工作,然后将释放互斥锁答案 1 :(得分:2)
pthread_cond_wait()
必须在发出信号/唤醒后获得给定的互斥量。如果另一个线程赢得该竞争,该函数将阻塞,直到释放互斥锁。因此从应用程序的角度来看,它不会返回,直到当前线程持有互斥锁。等待总是在循环中完成(上面while (avail == 0) { ...
)以确保我们正在等待的应用程序条件仍然保持(缓冲区不为空,更多可用工作等)
希望这有帮助。
答案 2 :(得分:1)
一旦互斥锁解锁,丢失比赛的线程就会唤醒,再次检查条件,然后在条件变量上进入睡眠状态。
答案 3 :(得分:0)
啊,但事实并非如此。不是“自动”,也就是说,取决于“自动”的含义。您可能会对当其中任何一个从pthread_cond_wait()返回时,它会自动声明互斥锁。
$(this).closest('div.theaterPlayer').remove(); //Removes all given(html) Div's and show length as 0;
的“原子”语义感到困惑;但是这个语义在入口端播放:一个线程以某种方式注册,在放弃互斥锁之前等待条件,因此没有任何窗口,在此期间线程不再具有互斥锁,并且还没有等待关于变量。
从pthread_cond_wait
返回的每个线程都必须获取互斥锁并因此争用它。那些失去互斥体竞争的人必须阻止互斥锁,就好像他们叫pthread_cond_wait
一样。
从pthread_mutex_lock
退出时获取互斥锁的方式可以建模为常规pthread_cond_wait
操作。本质上,线程必须在互斥锁上排队才能退出。获取互斥锁的每个线程然后从该函数返回;其他人必须等到该线程在允许返回之前放弃互斥锁。
信号唤醒的线程没有“自动”获取互斥锁,在某种意义上由于特殊资格而转移所有权。首先,在多处理器上,唤醒线程可能会丢失已经在另一个处理器上运行的线程的竞争,该处理器抢占互斥锁(如果可用),或者排队等待接收信号的线程之前的互斥锁。其次,调用pthread_mutex_lock
的线程本身可能没有放弃互斥锁,并且可能会无限期地继续保持它,这意味着所有唤醒线程将在互斥锁操作上排队,并且不会从{{{{{ 1}}直到该线程放弃互斥锁。
所有“自动”是pthread_cond_signal
操作在再次获取互斥锁之前不会返回,因此应用程序不必采取步骤来获取互斥锁。