这是这个非常好的文章的延续:https://stackoverflow.com/a/33500554/22598822。该帖子适用于序列 (t1 & t2) --> t3。假设我有一个程序正在运行,并且我想在内部执行序列 t1 --> t2 --> t3 中保留三个线程(其他线程可能会或可能不会在系统上同时运行)。怎么办?
我从上面的参考文献中获取了代码,并尝试为了这个目标重新编写它,但没有成功。我的实现不正确,我将其放在这里是为了一个最小的可重现示例,也许是一个可能的起点。
标头.h:
#include<thread>
#include<mutex>
#include<iostream>
#include <condition_variable>
MultiClass.h
#include "Header.h"
#include "SynchObj.h"
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.waitForCompletionOfT3();
std::cout << "T1:" << i << std::endl;
obj.signalCompletionOfT1();
}
}
void Calc2() {
for (int i = 0; i < 10; ++i) {
obj.waitForCompletionOfT1();
std::cout << "T2:" << i << std::endl;
obj.signalCompletionOfT2();
}
}
void Calc3() {
for (int i = 0; i < 10; ++i) {
obj.waitForCompletionOfT2();
std::cout << "T3:" << i << std::endl;
obj.signalCompletionOfT3();
}
}
};
SynchObj.h
#include "Header.h"
class SyncObj {
std::mutex mux;
std::condition_variable cv;
bool completed[3]{ false, false, false };
public:
/***** Original (t1 & t2) --> t3 *****/
/*
void signalCompetionT1T2(int id) {
std::lock_guard<std::mutex> ul(mux);
completed[id] = true;
cv.notify_all();
}
void signalCompetionT3() {
std::lock_guard<std::mutex> ul(mux);
completed[0] = false;
completed[1] = false;
cv.notify_all();
}
void waitForCompetionT1T2() {
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, [&]() {return completed[0] && completed[1]; });
}
void waitForCompetionT3(int id) {
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, [&]() {return !completed[id]; });
}
*/
/***********************************/
/*** Unsuccessful attempt at t1 --> t2 --> t3 ***/
void signalCompletionOfT1() {
std::lock_guard<std::mutex> ul(mux);
completed[0] = true;
cv.notify_all();
}
void signalCompletionOfT2() {
std::lock_guard<std::mutex> ul(mux);
completed[0] = false;
completed[1] = true;
cv.notify_all();
}
void signalCompletionOfT3() {
std::lock_guard<std::mutex> ul(mux);
completed[0] = false;
completed[1] = false;
completed[2] = true;
cv.notify_all();
}
void waitForCompletionOfT1() {
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, [&]() {return !completed[2]; });
}
void waitForCompletionOfT2() {
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, [&]() {return !completed[0]; });
}
void waitForCompletionOfT3() {
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, [&]() {return !completed[1]; });
}
};
来源.cpp:
#include "Header.h"
#include "MultiClass.h"
int main() {
MultiClass m;
m.Run();
return 0;
}
可能的输出#1(所需):
T1:1
T1:2
T1:3
T1:4
T1:5
T1:6
T1:7
T1:8
T1:9
T2:0
T2:1
T2:2
T2:3
T2:4
T2:5
T2:6
T2:7
T2:8
T2:9
T3:0
T3:1
T3:2
T3:3
T3:4
T3:5
T3:6
T3:7
T3:8
T3:9
可能的输出#2:
0
T2:1
T2:2
T2:3
T2:4
T2:5
T2:6
T2:7
T2:8
T2:9
对于此应用程序,使用信号量会更直接一些。以下程序输出您可能的输出#1:
使用 g++ 12.2.1 使用命令行编译:g++ -std=c++20 -pthread MultiClass.cpp
多类.cpp
#include<thread>
#include<mutex>
#include<iostream>
#include<semaphore>
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:
std::binary_semaphore t1{1};
std::binary_semaphore t2{0};
std::binary_semaphore t3{0};
void Calc1() {
t1.acquire();
for (int i = 0; i < 10; ++i) {
std::cout << "T1:" << i << std::endl;
}
t2.release();
}
void Calc2() {
t2.acquire();
for (int i = 0; i < 10; ++i) {
std::cout << "T2:" << i << std::endl;
}
t3.release();
}
void Calc3() {
t3.acquire();
for (int i = 0; i < 10; ++i) {
std::cout << "T3:" << i << std::endl;
}
}
};
int main() {
MultiClass m;
m.Run();
return 0;
}
顺便说一句,在您的代码中,您需要在开始完成数组时将其中一个设置为 true。
bool completed[3]{ true, false, false };