繁体   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