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

如何在C++中实现三个线程按t1→t2→t3顺序同步执行?

实现线程严格按t1→t2→t3顺序执行的正确方案

基于Stack Overflow的一篇帖子延伸,原帖实现了t1 & t2并行执行完成后再执行t3的逻辑。现需求为让三个线程严格按t1全部执行完毕→t2全部执行完毕→t3全部执行完毕的顺序执行(系统可同时运行其他线程)。

以下是错误实现的最小可复现代码,以及期望输出和实际错误输出:


错误实现代码

Header.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]; });           
    }

};

Source.cpp

#include "Header.h"
#include "MultiClass.h"

int main() {
    MultiClass m;
    m.Run();
    return 0;
}

期望输出

T1:0
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

实际错误输出示例

0
T2:1
T2:2
T2:3
T2:4
T2:5
T2:6
T2:7
T2:8
T2:9

错误原因分析

原实现的核心问题在于SyncObj的等待与信号逻辑完全错位:

  • 初始状态下completed[2]为false,T1的waitForCompletionOfT3()直接通过,但T1每次循环的等待条件和T3是否完成无关,逻辑混乱。
  • T2的等待条件判断的是!completed[2],这和T1是否完成没有关联,导致T2可能在T1未完成时就开始执行。
  • 信号函数中错误修改其他线程的状态标记,比如signalCompletionOfT2()将completed[0]设为false,会导致T1可以再次进入循环,破坏了"t1全部执行完再执行t2"的核心需求。

正确实现方案

要实现t1全部执行完毕后t2才开始,t2全部执行完毕后t3才开始,我们可以用阶段标记+条件变量的方式,跟踪当前允许执行的线程阶段,具体实现如下:

修改后的SynchObj.h

#include "Header.h"

class SyncObj {
    std::mutex mux;
    std::condition_variable cv;
    // 0: 允许T1执行,1: 允许T2执行,2: 允许T3执行
    int allowed_stage = 0;

public:
    // T1执行完成后,切换到允许T2执行的阶段
    void signalT1Done() {
        std::lock_guard<std::mutex> ul(mux);
        allowed_stage = 1;
        cv.notify_all();
    }

    // T2等待T1执行完成
    void waitForT1Done() {
        std::unique_lock<std::mutex> ul(mux);
        cv.wait(ul, [this]() { return allowed_stage == 1; });
    }

    // T2执行完成后,切换到允许T3执行的阶段
    void signalT2Done() {
        std::lock_guard<std::mutex> ul(mux);
        allowed_stage = 2;
        cv.notify_all();
    }

    // T3等待T2执行完成
    void waitForT2Done() {
        std::unique_lock<std::mutex> ul(mux);
        cv.wait(ul, [this]() { return allowed_stage == 2; });
    }
};

修改后的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) {
            std::cout << "T1:" << i << std::endl;
        }
        // T1全部执行完毕,通知T2可以开始
        obj.signalT1Done();
    }
    void Calc2() {
        // 等待T1全部执行完成
        obj.waitForT1Done();
        for (int i = 0; i < 10; ++i) {
            std::cout << "T2:" << i << std::endl;
        }
        // T2全部执行完毕,通知T3可以开始
        obj.signalT2Done();
    }
    void Calc3() {
        // 等待T2全部执行完成
        obj.waitForT2Done();
        for (int i = 0; i < 10; ++i) {
            std::cout << "T3:" << i << std::endl;
        }
    }
};

方案说明

  • 用allowed_stage变量标记当前允许执行的线程阶段,初始值为0(允许T1执行)。
  • T1无需等待,直接执行完所有循环后,将阶段切换为1并通知所有等待的线程,T2收到通知后开始执行。
  • T2执行完所有循环后,将阶段切换为2并通知,T3收到通知后开始执行。
  • 这种方式严格保证了t1全部执行完毕后t2才启动,t2全部执行完毕后t3才启动,完全符合需求。

内容的提问来源于stack exchange,提问作者barak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:35:55