[英]Synchronize three Threads in C++
我有以下程序(組成示例!):
#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
將執行一次,然后t3
將執行一次。
因此,您看到,我需要t1
和t2
同時執行操作,並且在進行一次迭代之后, t3
應該自己進行一次迭代。
您能否指出我將如何實現這一目標? 就像我說的,我一直在嘗試使用互斥鎖,但無法提出解決方案。
使用兩個條件變量,這是一個草圖。
線程1和2等待條件變量segment_1
:
std::condition_variable segment_1;
線程3等待條件變量segment_2
;
std::condition_variable segment_2;
線程1和2應該在segment_1
上使用wait()
,線程3應該在segment_2
上使用wait()
。 要啟動線程1和2,請在segment_1
上調用notify_all()
,一旦完成,請在segment_2
上調用notify_one()
來啟動線程3。您可能希望使用某些控制線程來控制序列,除非可以進行鏈接(即1和2完成后,最后一個要完成的調用將通知線程3,依此類推。)
這並不完美(請參閱丟失的喚醒)
如果您真的想使用給定的線程結構手動執行此操作,則可以使用以下方法*:
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。
*)注意:此代碼未經測試且未經優化。 我只是寫了它,以表明總體結構是什么樣子
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.