【发布时间】:2021-10-22 05:48:52
【问题描述】:
cppreference.com 的条件变量 notify_one() 函数的文档说明如下
通知线程不需要持有与等待线程持有的互斥锁相同的互斥锁;实际上这样做是一种悲观,因为被通知的线程会立即再次阻塞,等待通知线程释放锁。
这句话的第一部分很奇怪,如果我在 notifying 和 notified 线程中持有不同的互斥锁,那么互斥锁就没有真正的意义,因为没有这里的“阻塞”操作。事实上,如果持有不同的互斥锁,那么虚假唤醒可能导致错过通知是可能的!我的印象是,在这种情况下,我们最好不要锁定 notifying 线程。有人可以澄清一下吗?
以条件变量的 cppreference 页面为例。
std::mutex m; // this is supposed to be a pessimization
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m); // a different, local std::mutex is supposedly better
cv.wait(lk, []{return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing data\n";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completed\n";
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m); // a different, local std::mutex is supposedly better
ready = true;
std::cout << "main() signals data ready for processing\n";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
}
std::cout << "Back in main(), data = " << data << '\n';
worker.join();
}
PS。我看到了一些标题相似的问题,但它们涉及问题的不同方面。
【问题讨论】:
-
您的印象是正确的。这句话的措辞可能很尴尬,但意思是通知线程不需要持有与条件变量关联的互斥锁来通知它。它可能持有也可能不持有其他不相关的互斥锁。
-
我不确定您的问题到底是什么。请注意,在 cppreference 示例中,互斥锁
m在调用cv.notify_one()时不由主线程持有。 -
@NateEldredge 非常感谢!固定。
标签: c++ multithreading condition-variable