【发布时间】:2018-09-25 17:01:34
【问题描述】:
查看several videos 和documentation example,我们在调用notify_all() 之前解锁互斥锁。之后调用它会更好吗?
常用方式:
Notifier 线程内部:
//prepare data for several worker-threads;
//and now, awaken the threads:
std::unique_lock<std::mutex> lock2(sharedMutex);
_threadsCanAwaken = true;
lock2.unlock();
_conditionVar.notify_all(); //awaken all the worker threads;
//wait until all threads completed;
//cleanup:
_threadsCanAwaken = false;
//prepare new batches once again, etc, etc
在其中一个工作线程内:
while(true){
// wait for the next batch:
std::unique_lock<std::mutex> lock1(sharedMutex);
_conditionVar.wait(lock1, [](){return _threadsCanAwaken});
lock1.unlock(); //let sibling worker-threads work on their part as well
//perform the final task
//signal the notifier that one more thread has completed;
//loop back and wait until the next task
}
注意lock2 在我们通知条件变量之前是如何解锁的 - 我们是否应该在notify_all() 之后 解锁它?
编辑
来自我下面的评论:我担心的是,如果消费者超级快怎么办。消费者虚假地醒来,看到互斥锁被解锁,完成任务并循环回到 while 的开始。现在,slow-poke Producer 最终调用了 notify_all(),导致 consumer 循环了额外的时间。
【问题讨论】:
-
lock2的析构函数调用将在_conditionVar.notify_all();之后自动解锁互斥锁,因此您根本不需要显式调用它,这是常见的成语IIRC。顺便说一句,不要在任何代码中使用前缀下划线,这是为编译器和标准库实现保留的。 -
谢谢!我担心的是,如果消费者超级快怎么办。消费者突然醒来,看到互斥锁已解锁,完成任务并循环回到
while的开头。现在慢戳生产者终于调用notify_all(),导致消费者循环额外的时间。
标签: c++ multithreading condition-variable