在C ++中同步三个线程

时间:2015-11-03 12:23:06

标签: c++ multithreading

我有以下程序(编写示例!):

#include<thread>
#include<mutex>
#include<iostream>

class MultiClass {
    public:
        void Run() {
            std::thread t1(&MultiClass::Calc, this);
            std::thread t2(&MultiClass::Calc, this);
            std::thread t3(&MultiClass::Calc, this);
            t1.join();
            t2.join();
            t3.join();
        }
    private:
        void Calc() {
            for (int i = 0; i < 10; ++i) {
                std::cout << i << std::endl;
            }
        }
};

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

我需要的是以下面的方式同步循环迭代,我不能提出一个解决方案(我现在使用互斥体摆弄了大约一个小时,但是找不到组合): t1t2应进行一次循环迭代,然后t3将进行一次迭代,然后再次t1t2执行一次,然后{{1}应该做一个。

所以你看,我需要t3t1同时做事,经过一次迭代后,t2将自己进行一次迭代。

你能指出我将如何实现这一目标吗?就像我说的那样,我一直在尝试使用互斥量,并且无法提出解决方案。

2 个答案:

答案 0 :(得分:1)

使用两个条件变量,这里是草图..

主题1&amp; 2等待条件变量segment_1

std::condition_variable segment_1;

线程3等待条件变量segment_2;

std::condition_variable segment_2;

线程1&amp; 2 wait()上的segment_1应该wait()上的segment_2notify_all()上的{3}应该segment_1。开始线程1&amp; 2,在notify_one()上致电segment_2,完成后,在static Session上调用SessionFactory以启动话题3.您可能需要使用某个控制线程来控制序列除非你可以链接(即一旦1和2完成,最后一个完成调用通知线程3等等)。

这并不完美(见失败的唤醒)

答案 1 :(得分:1)

如果你真的想用给定的线程结构手动完成这个,你可以使用这样的东西*:

class SyncObj {
    mutex mux;
    condition_variable cv;  
    bool completed[2]{ false,false };

public:
    void signalCompetionT1T2(int id) {
        lock_guard<mutex> ul(mux);
        completed[id] = true;
        cv.notify_all();
    }
    void signalCompetionT3() {
        lock_guard<mutex> ul(mux);
        completed[0] = false;
        completed[1] = false;
        cv.notify_all();
    }
    void waitForCompetionT1T2() {
        unique_lock<mutex> ul(mux);             
        cv.wait(ul, [&]() {return completed[0] && completed[1]; });         
    }
    void waitForCompetionT3(int id) {
        unique_lock<mutex> ul(mux);         
        cv.wait(ul, [&]() {return !completed[id]; });           
    }       
};

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.waitForCompetionT3(0);
            std::cout << "T1:" << i << std::endl;
            obj.signalCompetionT1T2(0);
        }           
    }
    void Calc2() {
        for (int i = 0; i < 10; ++i) {
            obj.waitForCompetionT3(1);
            std::cout << "T2:" << i << std::endl;
            obj.signalCompetionT1T2(1);
        }
    }
    void Calc3() {      
        for (int i = 0; i < 10; ++i) {
            obj.waitForCompetionT1T2();
            std::cout << "T3:" << i << std::endl;
            obj.signalCompetionT3();
        }       
    }
};

但是,这只是一种合理的方法,如果每次迭代都是计算成本高的,那么您可以忽略同步开销。如果不是这样的话,你应该更好地看一下正确的并行编程库,比如intel的tbb或microsofts ppl。

*)注意:此代码未经测试且未经优化。我只是写它来显示一般结构可能是什么样的