我有以下程序(编写示例!):
#include<thread>
#include<mutex>
#include<iostream>
class MultiClass {
public:
void Run() {
std::thread t1(&MultiClass::Calc, this);
std::thread t2(&MultiClass::Calc, this);
std::thread t3(&MultiClass::Calc, this);
t1.join();
t2.join();
t3.join();
}
private:
void Calc() {
for (int i = 0; i < 10; ++i) {
std::cout << i << std::endl;
}
}
};
int main() {
MultiClass m;
m.Run();
return 0;
}
我需要的是以下面的方式同步循环迭代,我不能提出一个解决方案(我现在使用互斥体摆弄了大约一个小时,但是找不到组合):
t1
和t2
应进行一次循环迭代,然后t3
将进行一次迭代,然后再次t1
和t2
执行一次,然后{{1}应该做一个。
所以你看,我需要t3
和t1
同时做事,经过一次迭代后,t2
将自己进行一次迭代。
你能指出我将如何实现这一目标吗?就像我说的那样,我一直在尝试使用互斥量,并且无法提出解决方案。
答案 0 :(得分:1)
使用两个条件变量,这里是草图..
主题1&amp; 2等待条件变量segment_1
:
std::condition_variable segment_1;
线程3等待条件变量segment_2
;
std::condition_variable segment_2;
线程1&amp; 2 wait()
上的segment_1
应该wait()
上的segment_2
,notify_all()
上的{3}应该segment_1
。开始线程1&amp; 2,在notify_one()
上致电segment_2
,完成后,在static Session
上调用SessionFactory
以启动话题3.您可能需要使用某个控制线程来控制序列除非你可以链接(即一旦1和2完成,最后一个完成调用通知线程3等等)。
这并不完美(见失败的唤醒)
答案 1 :(得分:1)
如果你真的想用给定的线程结构手动完成这个,你可以使用这样的东西*:
class SyncObj {
mutex mux;
condition_variable cv;
bool completed[2]{ false,false };
public:
void signalCompetionT1T2(int id) {
lock_guard<mutex> ul(mux);
completed[id] = true;
cv.notify_all();
}
void signalCompetionT3() {
lock_guard<mutex> ul(mux);
completed[0] = false;
completed[1] = false;
cv.notify_all();
}
void waitForCompetionT1T2() {
unique_lock<mutex> ul(mux);
cv.wait(ul, [&]() {return completed[0] && completed[1]; });
}
void waitForCompetionT3(int id) {
unique_lock<mutex> ul(mux);
cv.wait(ul, [&]() {return !completed[id]; });
}
};
class MultiClass {
public:
void Run() {
std::thread t1(&MultiClass::Calc1, this);
std::thread t2(&MultiClass::Calc2, this);
std::thread t3(&MultiClass::Calc3, this);
t1.join();
t2.join();
t3.join();
}
private:
SyncObj obj;
void Calc1() {
for (int i = 0; i < 10; ++i) {
obj.waitForCompetionT3(0);
std::cout << "T1:" << i << std::endl;
obj.signalCompetionT1T2(0);
}
}
void Calc2() {
for (int i = 0; i < 10; ++i) {
obj.waitForCompetionT3(1);
std::cout << "T2:" << i << std::endl;
obj.signalCompetionT1T2(1);
}
}
void Calc3() {
for (int i = 0; i < 10; ++i) {
obj.waitForCompetionT1T2();
std::cout << "T3:" << i << std::endl;
obj.signalCompetionT3();
}
}
};
但是,这只是一种合理的方法,如果每次迭代都是计算成本高的,那么您可以忽略同步开销。如果不是这样的话,你应该更好地看一下正确的并行编程库,比如intel的tbb或microsofts ppl。
*)注意:此代码未经测试且未经优化。我只是写它来显示一般结构可能是什么样的