簡體   English   中英

解決死鎖問題,在主線程中等待多個工作線程完成(C ++ 11)

[英]Resolve deadlock issue, waiting in the main thread for multiple worker threads to finish (C++11)

我正在嘗試使用c ++ 11編寫一個程序,其中運行多個線程,並且在每個周期中,主線程將等待每個線程完成。 下面的程序是針對此概念的測試程序。

顯然,我在實現中缺少一些瑣碎的事情,因為看起來好像遇到了死鎖(並非總是如此,只是在某些隨機運行期間)。

#include <iostream>
#include <stdio.h>
#include <thread>
#include <chrono>
#include <condition_variable>
#include <mutex>

using namespace std;

class Producer
{
public:
    Producer(int a_id):
        m_id(a_id),
        m_ready(false),
        m_terminate(false)
    {
        m_id = a_id;
        m_thread = thread(&Producer::run, this);
        // ensure thread is available before it is started
        this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    ~Producer() {
        terminate();
        m_thread.join();
    }

    void start() {
        //cout << "start " << m_id << endl;
        unique_lock<mutex> runLock(m_muRun);
        m_ready = true;
        runLock.unlock();
        m_cond.notify_all();
    }

    void wait() {
        cout << "wait " << m_id << endl;
        unique_lock<decltype(m_muRun)> runLock(m_muRun);
        m_cond.wait(runLock, [this]{return !m_ready;});
    }

    void terminate() {
        m_terminate = true;
        start();
    }

    void run() {
        do {
            unique_lock<decltype(m_muRun)> runLock(m_muRun);
            m_cond.wait(runLock, [this]{return m_ready;});

            if (!m_terminate) {
                cout << "running thread: " << m_id << endl;
            } else {
                cout << "exit thread: " << m_id << endl;
            }

            runLock.unlock();
            m_ready = false;
            m_cond.notify_all();
        } while (!m_terminate);
    }

private:
    int m_id;
    bool m_ready;
    bool m_terminate;
    thread m_thread;

    mutex m_muRun;
    condition_variable m_cond;
};

int main()
{
    Producer producer1(1);
    Producer producer2(2);
    Producer producer3(3);

    for (int i=0; i<10000; ++i) {
        cout << i << endl;
        producer1.start();
        producer2.start();
        producer3.start();

        producer1.wait();
        producer2.wait();
        producer3.wait();
    }

    cout << "exit" << endl;
    return 0;
}

發生死鎖時程序的輸出:

....
.......
running thread: 2
running thread: 1
wait 1
wait 2
wait 3
running thread: 3

看一下發生死鎖時程序的輸出,我懷疑程序的瓶頸在於有時會在實際啟動相應線程之前調用Producer::wait函數,即命令Producer::start應該已經觸發了啟動, ak互斥鎖的解鎖,但是尚未被線程的run方法( Producer::run )接受,(注意:我對此不是100%肯定!)。 我在這里迷路了,希望有人能提供幫助。

您的代碼中存在比賽條件:

   runLock.unlock();
   m_ready = false;

m_ready變量必須始終受互斥保護,以實現正確的同步。 而且完全沒有必要等待線程啟動this_thread::sleep_for() -適當的同步也可以解決該問題,因此您只需刪除該行即可。 請注意,這是進行正確的多線程處理的效率非常低的方法-應該有線程池,而不是每個對象都有單獨的互斥量和條件變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM