提问人:TommyBe 提问时间:11/14/2023 最后编辑:genpfaultTommyBe 更新时间:11/16/2023 访问量:69
如何将这种特殊情况的线程与 C++ std::thread 同步
How to synchronize this special case of threads with C++ std::thread
问:
对于以下情况,我需要一些帮助:我有一个主程序,可以启动与线程相同的函数的多个实例。被调用的函数至少分为两部分。首先,每个实例都必须执行函数的第 1 部分,然后才能继续执行第 2 部分。在这里,我需要同步它们。为了更易于理解,我将编写一些示例代码:
void TMainForm::foo(int numThreads)
{
std::cout << "Part 1: do some work" << std::endl;
/* HERE NEEDS TO BE SOMETHING THAT CHECKS WHETHER EVERY INSTANCE HAS DONE PART 1 !!*/
std::cout << "Part 2: do some work" << std::endl;
}
//---------------------------------------------------------------------------
void TMainForm::StartingThreads()
{
int threads = std::thread::hardware_concurrency();
std::vector<std::thread> t(threads);
for (int i = 0; i < threads; i++)
t[i] = std::thread(foo, threads);
for (int i = 0; i < threads; i++)
t[i].join();
}
//---------------------------------------------------------------------------
我尝试使用互斥锁,但它对我不起作用。我递增了一个原子变量(比如说原子 a),如果该值小于 numThreads,我执行了互斥锁::锁定。当最后一个实例完成它的工作时,它会完成一个互斥锁::解锁。但是我的线程在第 1 部分之后总是卡住了。
有人有什么想法吗?
答:
0赞
Joseph Larson
11/15/2023
#1
如果你使用的是 C++ 20,那么其他人已经给了你答案。如果你年满 17 岁,那么我会做一个你可以疯狂地进行单元测试的课程。
class Barrier {
public:
Barrier(int dc = 1): desiredCount(dc) {}
void done() {
std::unique_lock<std::mutex> lock(mutex);
++doneCount;
condVar.notify_all();
}
void waitReady() {
std::unique_lock<std::mutex> lock(mutex);
while (doneCount < desiredCount) {
condVar.wait(lock);
}
}
private:
std::mutex mutex;
std::cond_var condVar;
int desiredCount = 1;
int doneCount = 0;
};
然后在代码中,将其中一个初始化为线程数,然后在线程中:
barrier.done();
barrier.waitReady();
我正在写这个 - 可能不是完美的代码。还有其他方法可以使用 wait(您可以传递谓词),但这是我经常使用的模式。
评论
0赞
TommyBe
11/15/2023
谢谢!这对我来说也很好,尤其是对于较旧的 c++ 版本!我想在您的 done() 函数中,您想增加 doneCount 而不是 desiredCount?我不能给你点赞,因为我是新来的。
0赞
Joseph Larson
11/16/2023
@TommyBe 你对 done() 方法的看法是正确的,我会解决这个问题。
评论
std::latch
(或 ,这是一个多用途闩锁)。std::barrier
std::latch
std::barrier
std::jthread
std::thread
join