我正在尝试解决以下架构,但遇到了一些麻烦。
基本上有多个线程并行访问同一个对象。第一个线程意味着执行Object.A()
,所有其他线程应该等到该过程完成后再继续执行Object.B()
而不会有任何阻塞。
无法在网上找到任何可以解释任何会产生此功能的资源以及任何解决方案"用2个自定义布尔互斥体跳出来的想法似乎不起作用。
答案 0 :(得分:2)
我不会详细介绍实施细节,但就方法而言,您正在寻找的是来自The little book of semaphores的障碍解决方案。
障碍问题 是让所有线程在会合点相遇,然后全部继续执行关键部分(在你的情况下Object.B())。在 rendezvous 点开会之前,只有第一个线程执行Object.A()并在rendezvous处加入线程。在同一本书中查看Reader的编写器问题,以了解如何使第一个线程执行/调用Object.A()
答案 1 :(得分:1)
如果您想要并行方式,请使用conditial变量为Object.B()启动线程。但是Object.B()必须是线程安全的。
答案 2 :(得分:1)
NathanOliver在评论中建议的方法是在主线程上调用A()
然后然后调整其他线程,这是最简单的方法,也是你应该考虑的第一个方法。 / p>
但是你正在寻找的构造称为“monitor”(你丢失的那个被称为“条件变量”,“监视器”指的是你将要使用的整个互斥+ cond变量对需要)。
我不会在这里重现示例,因为很容易找到信息(Travis Gockel just posted a nice example)。取决于您的线程子系统:
一次性运行的一般模型是:
A()
B()
如果要重复该过程,则必须在运行所有B()
之后重置条件,并在再次调用A()
之前等待该状态。您可以使用另一个cond var来执行此操作,您可以使用信号量和一些小心等来执行此操作。
我知道这很简短,但希望它至少能为您提供一些搜索关键字。
有用的额外阅读:
或者看一下带有任务队列的线程池。您可以对运行A()
的任务进行排队,然后在完成任务时将一堆B()
任务排入队列(可选地,这些B()
任务可以维护共享信号量或只是一个基本的线程安全计数器 - Windows上的InterlockedDecrement
和volatile
计数器可以让这个非常简单 - 监控他们的进度,因此最后一个可以重新排列A()
跑步者并重复一次。)
答案 3 :(得分:1)
假设您正在使用C ++ 11(或更高版本),可以使用std::mutex
,std::condition_variable
和bool
来完成此操作。一小段示例代码...
#include <condition_variable>
#include <mutex>
class Object
{
public:
Object() :
ready(false)
{ }
void A()
{
// do preparation work here
// Then, you set ready to true and notify all potential waiters in B:
std::unique_lock<std::mutex> lock(protect);
ready = true;
ready_cond.notify_all();
}
void B()
{
if (!ready)
{
// Only go into blocking if A isn't done yet
std::unique_lock<std::mutex> lock(protect);
while (!ready)
ready_cond.wait(lock);
}
// do shared work at this point
}
private:
std::mutex protect;
bool ready;
std::condition_variable ready_cond;
};
这并不能保护您免受多人打电话A
,再次打电话或可能发生的任何事情,但这只是一个起点。