提问人:hdnn 提问时间:8/1/2020 更新时间:8/2/2020 访问量:522
C++。std::condition_variable 和多个等待线程
C++. std::condition_variable and multiple wait-threads
问:
我有一些类,带有 of 成员和方法和 .queue
std::function<void()>
Push
Pop
我想实现加法。当你有一个(谁打电话)和一个(谁打电话)时,这很容易 - 简单就足够了。PushAndWaitUntilExecuted
consumer-thread
Pop
producer-thread
Push
std::condition_variable
但是我的应用程序具有动态数量的线程,它们可以并行执行相同的代码行和调用函数,并等待执行推送的对象。PushAndWaitUntilExecuted
consumer-thread
std::function
A 有传递给的想法,而不仅仅是 ,其中 - ()。然后调用,所有线程将检查执行的线程是否与线程相同。std::pair<uint64_t, std::function<void()>>
queue
std::function<void()>
uint64_t
producer-thread ID
boost::this_thread::get_id()
consumer-thread
std::condition_variable::notify_all()
std::function
ID
是可以的解决方案还是可以实施更好的东西?
答:
这里需要引入的不仅仅是一个条件变量,以避免几个不同的竞争条件。还需要互斥锁和作业完成标志。
在这一点上,用包含此封口以及所有额外行李的小班替换您的行李会变得更干净:std::function<void()>
struct job {
std::function<void()> implementation;
std::mutex m;
std::condition_variable flag;
bool completed=false;
};
您的队列变成了 s 的队列,而不是 s 的队列,作业在动态范围内构造(当然,因为互斥锁和条件变量不可复制或不可移动,并且这些对象可以从您的两个线程访问)。std::shared_ptr<job>
std::function
工作线程完成执行实现后,它会:
- 锁定互斥锁。
- 设置为 true
completed
- 表示条件变量。
而你的 ,在它执行推送后:PushAndWaitUntilExecuted
- 锁定互斥锁
- 等待条件变量,直到设置
completed
您必须彻底了解,C++ 绝对不能保证,在将新闭包推入作业队列后,某些线程不会立即抓住它,执行它并完成它,然后原始线程(推动它的线程)开始查看条件变量。到现在为止,没有人会再向条件变量发出信号了。如果你在这里只需要一个条件变量,那么你将等待条件变量发出信号,直到我们的太阳爆炸。
这就是为什么你需要的不仅仅是一个条件变量、一个互斥锁和一个显式标志,并使用上述方法来正确处理线程间排序。
这是一种相当经典的常规方法。您应该在每本关于此主题的优秀 C++ 教科书中找到许多类似实现的示例。
评论