std::condition_variable::notify_all() - 我需要一个例子
Posted
技术标签:
【中文标题】std::condition_variable::notify_all() - 我需要一个例子【英文标题】:std::condition_variable::notify_all() - I need an example 【发布时间】:2017-05-03 12:06:53 【问题描述】:我需要一个使用 notify_all() 方法的示例。因为我无法理解它应该如何工作。
每个等待线程都以这样的代码开始:
std::unique_lock<std::mutex> lock(mutex);
condition_variable.wait(lock, []()return SOMETHING;);
一开始,等待线程需要获取一个互斥体。因此,如果有多个等待线程,其余线程将等待锁定互斥体。那么,如果等待线程卡在锁定互斥体上并且根本不执行方法 wait(),那么使用 notify_all() 的目的是什么?这些线程将一一唤醒,而不是同时唤醒。
【问题讨论】:
让我引导您到一个很好的参考/示例网站:en.cppreference.com/w/cpp/thread/condition_variable 它不能解决我的问题。对不起。 【参考方案1】:互斥锁保护condition_variable
的内部状态。在condition_variable
上调用wait
会导致互斥锁被解锁。所以在等待时,线程并不拥有互斥锁。
当wait
完成时,在对wait
的调用返回之前再次(原子地)获取互斥锁。
线程不是在互斥体上竞争,而是在条件本身上竞争。
如果您愿意,您可以在等待返回后立即解锁。例如,如果你想允许多个线程在一个条件下同步,你会这样做。您还可以使用此功能来实现信号量。
示例:
此代码以 10 个为一组处理事物。请注意,notify_all()
位于 unlock()
之后:
#include <condition_variable>
#include <mutex>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <vector>
void emit(std::string const& s)
static std::mutex m;
auto lock = std::unique_lock<std::mutex>(m);
std::cout << s << std::endl;
std::mutex m;
std::condition_variable cv;
int running_count = 0;
void do_something(int i)
using namespace std::literals;
auto lock = std::unique_lock<std::mutex>(m);
// mutex is now locked
cv.wait(lock, // until the cv is notified, the mutex is unlocked
[]
// mutex has been locked here
return running_count < 10;
// if this returns false, mutex will be unlocked again, but code waits inside wait() for a notify()
);
// mutex is locked here
++running_count;
lock.unlock();
// we are doing work after unlocking the mutex so others can also
// work when notified
emit("running " + std::to_string(i));
std::this_thread::sleep_for(500ms);
// manipulating the condition, we must lock
lock.lock();
--running_count;
lock.unlock();
// notify once we have unlocked - this is important to avoid a pessimisation.
cv.notify_all();
int main()
std::vector<std::thread> ts;
for (int i = 0 ; i < 200 ; ++i)
ts.emplace_back([i] do_something(i); );
for (auto& t : ts)
if (t.joinable()) t.join();
【讨论】:
你的意思是wait()方法解锁互斥锁吗? @AkasataAkasata wait 同时解锁互斥锁并在条件变量上进入等待状态。当通知条件变量时,所有等待者重新获取锁以测试条件。我将注释代码。 所以如果他们按顺序重新获取锁,notify_all() 也会按顺序唤醒他们,对吧? @RichardHodges,在任何给定时间,只有一个线程可以持有lock
,并且cv.wait()
不可能在线程持有锁之前返回。所以,是的,它同时唤醒它们,但“唤醒”仅意味着线程从条件变量的队列移动到互斥队列。他们不会同时获得锁并从wait()
返回。
@jameslarge 同意。我认为我们需要比几行更长的时间来详细解释它。我认为,如果 Akasata 做一些背景阅读会更好。以上是关于std::condition_variable::notify_all() - 我需要一个例子的主要内容,如果未能解决你的问题,请参考以下文章
std::atomic 和 std::condition_variable 等待、notify_* 方法之间的区别
C++ std::condition_variable wait() wait_for() 区别 怎么用 实例
如何正确使用 std::condition_variable?
std::condition_variable::notify_all() - 我需要一个例子