C++互斥锁线程同步问题求助:迭代矩阵计算同步异常
迭代式多线程任务同步问题修复
你的代码核心问题是完全没有实现“所有线程完成任务A后再启动任务B”的同步约束,具体问题如下:
- 条件变量的
wait谓词直接返回true,相当于跳过等待逻辑,线程会直接执行后续代码,完全没有同步效果。 - 没有跟踪线程完成任务A的计数,无法判断何时所有线程都完成了A阶段,自然无法触发B阶段的统一启动。
以下是两种可靠的修复方案:
方案一:使用C++20 std::barrier(推荐)
std::barrier是标准库专门用于多线程同步的原语,能让指定数量的线程在某个点阻塞,直到所有线程都到达该点后再一起继续执行,完美匹配你的需求。
#include <thread> #include <vector> #include <barrier> int main() { const int Nthread = 2; const int Iterations = 3000; // 初始化两个屏障:分别在任务A、任务B完成后同步所有线程 std::barrier barrier_after_A(Nthread); std::barrier barrier_after_B(Nthread); std::vector<std::thread> threads; threads.reserve(Nthread); for (int thread_id = 0; thread_id < Nthread; ++thread_id) { threads.emplace_back([thread_id, &barrier_after_A, &barrier_after_B]() { for (int iter = 0; iter < Iterations; ++iter) { // 执行任务A:替换为你的矩阵计算逻辑 // printf("Thread %d: Iter %d - Job A done\n", thread_id, iter); // 等待所有线程完成任务A barrier_after_A.arrive_and_wait(); // 执行任务B:替换为你的矩阵计算逻辑 // printf("Thread %d: Iter %d - Job B done\n", thread_id, iter); // 等待所有线程完成任务B,进入下一轮迭代 barrier_after_B.arrive_and_wait(); } }); } for (auto& thread : threads) thread.join(); return 0; }
方案二:手动用计数器+条件变量实现(兼容C++11/17)
如果你的环境不支持C++20,可以手动用互斥锁、条件变量和计数器实现屏障逻辑:
#include <thread> #include <vector> #include <mutex> #include <condition_variable> int main() { const int Nthread = 2; const int Iterations = 3000; std::mutex mtx; std::condition_variable cv; int completed_A = 0; int completed_B = 0; std::vector<std::thread> threads; threads.reserve(Nthread); for (int thread_id = 0; thread_id < Nthread; ++thread_id) { threads.emplace_back([thread_id, &mtx, &cv, &completed_A, &completed_B]() { for (int iter = 0; iter < Iterations; ++iter) { // 执行任务A:替换为你的矩阵计算逻辑 // printf("Thread %d: Iter %d - Job A done\n", thread_id, iter); // 标记任务A完成并通知其他线程 { std::lock_guard<std::mutex> lock(mtx); completed_A++; } cv.notify_all(); // 等待所有线程完成任务A { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [&]() { return completed_A == Nthread; }); } // 执行任务B:替换为你的矩阵计算逻辑 // printf("Thread %d: Iter %d - Job B done\n", thread_id, iter); // 标记任务B完成,所有线程完成后重置计数器 { std::lock_guard<std::mutex> lock(mtx); completed_B++; if (completed_B == Nthread) { completed_A = 0; completed_B = 0; } } cv.notify_all(); // 等待计数器重置,确保下一轮迭代的同步状态正确 { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [&]() { return completed_A == 0 && completed_B == 0; }); } } }); } for (auto& thread : threads) thread.join(); return 0; }
注意事项
- 如果任务A/B涉及共享数据,需要额外添加互斥锁保护;如果是每个线程处理矩阵的独立分块,则无需额外同步。
std::barrier代码更简洁且不易出错,优先在支持C++20的环境中使用。
内容的提问来源于stack exchange,提问作者user19754998
相关产品推荐
相关产品推荐

