You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:42:51