通知线程做工作,并知道何时完成

时间:2018-02-17 19:22:37

标签: c++ multithreading

我有以下任务要做。我想启动一个线程管理器/池,它应该启动所有线程并等到有工作要做。然后我应该通知线程做什么工作,并且当它完成时我应该收到一个信号。我已经在下面实现了它,但似乎没有用。

class ThreadManager{
public:
    std::vector<std::thread> threads;
    std::vector<bool> threadCompletes;

    std::mutex sendMtx, recvMtx;
    std::condition_variable sendCv;

    static void thread_worker(int id, ThreadManager* manager){
        while(1){
            cout << "Thread Wait: " << id << endl;
            std::unique_lock<std::mutex> lck(manager->sendMtx);
            manager->sendCv.wait(lck);
            **lck.unlock();** # JUST ADDED THIS
            // DO WORK
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            manager->threadCompletes[id] = true;
            bool done = (std::find(std::begin(manager->threadCompletes), std::end(manager->threadCompletes), false) == std::end(manager->threadCompletes));
            cout << "Job Complete: " << id << endl;
            if(done){
                cout << "All Done" << endl;
                manager->recvMtx.unlock();
            }
        }
    }

    ThreadManager(){

    }

    void addThread(){
        threadCompletes.push_back(false);
        threads.push_back(std::thread(ThreadManager::thread_worker, threads.size(), this));
    }

    void signal(){
        for(auto i : threadCompletes) i = 0;
        recvMtx.lock();
        std::unique_lock<std::mutex> sendLck(sendMtx);
        sendCv.notify_all();
    }

    void wait(){
        recvMtx.lock();
        recvMtx.unlock();
    }

    void join(){
        for (int i = 0; i < threads.size(); ++i) {
            threads[i].join();
        }
    }
};


void test2(){

    ThreadManager manager;
    for(int i=0; i<5; i++){
        manager.addThread();
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    manager.signal();
    manager.wait();
    cout << "Complete" << endl;

    manager.join();

}

线程全部在等待调用时启动并阻塞,当我发出信号时,每个线程似乎只会随后运行。

Thread Wait: 0
Thread Wait: 1
Thread Wait: 2
Thread Wait: 3
Thread Wait: 4
Job Complete: 0
Thread Wait: 0
Job Complete: 1 # Done one after the other 500ms
Thread Wait: 1
Job Complete: 2 # Done one after the other 500ms
Thread Wait: 2
Job Complete: 3 # Done one after the other 500ms
Thread Wait: 3
Job Complete: 4 # Done one after the other 500ms
All Done
Thread Wait: 4
Complete

我做错了什么

修改

我添加了解锁标志。但是,现在如果我做这样的事情,它最终会失败:

for(int i=0; i<10; i++){
    manager.signal();
    manager.wait();
    cout << "Complete" << endl;
}

cout << "ALL DONE" << endl;

基本上,它运行到&#34;完成&#34; 2或3次,但它永远不会达到&#34;全部完成&#34;。还有一些其他竞争条件正在进行中

1 个答案:

答案 0 :(得分:0)

每个线程在其生命周期的大部分时间内锁定相同的互斥锁,包括大约500ms的睡眠操作,该操作只能在线程获得互斥锁后开始。这有效地防止了并发性并使多线程无用。

我根本不了解在工作线程中进行睡眠的目的,但如果有,则将其移动到互斥锁之外。一旦条件变量被唤醒就通过解锁来做到这一点;你不再需要它了;这将释放其他线程以便同时工作。