[英]Resolve deadlock issue, waiting in the main thread for multiple worker threads to finish (C++11)
I'm trying to write a program with c++11 in which multiple threads are run, and, during each cycle the main thread will wait for each thread to be finished. 我正在尝试使用c ++ 11编写一个程序,其中运行多个线程,并且在每个周期中,主线程将等待每个线程完成。 The program below is a testing program for this concept. 下面的程序是针对此概念的测试程序。
Apparently I'm missing something trivial in my implementation as it looks like I'm experiencing a deadlock (Not always, just during some random runs). 显然,我在实现中缺少一些琐碎的事情,因为看起来好像遇到了死锁(并非总是如此,只是在某些随机运行期间)。
#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;
}
The program's output when the deadlock is occurring: 发生死锁时程序的输出:
....
.......
running thread: 2
running thread: 1
wait 1
wait 2
wait 3
running thread: 3
Looking at the program's output when the deadlock occurs, I suspect the bottleneck of the program is that sometimes the Producer::wait
function is called, before the corresponding thread is actually started, ie the command Producer::start
should have triggered the start, ak unlocking of the mutex, however it is not yet picked up by the thread's run method ( Producer::run
), (NB: I'm not 100% sure of this!). 看一下发生死锁时程序的输出,我怀疑程序的瓶颈在于有时会在实际启动相应线程之前调用Producer::wait
函数,即命令Producer::start
应该已经触发了启动, ak互斥锁的解锁,但是尚未被线程的run方法( Producer::run
)接受,(注意:我对此不是100%肯定!)。 I'm a bit lost here, hopefully somebody can provide some help. 我在这里迷路了,希望有人能提供帮助。
You have race condition in this code: 您的代码中存在比赛条件:
runLock.unlock();
m_ready = false;
m_ready
variable must be always protected by mutex for proper synchronization. m_ready
变量必须始终受互斥保护,以实现正确的同步。 And it is completely unnecessary to wait for thread to start this_thread::sleep_for()
- proper synchronization would take care of that as well so you can simply remove that line. 而且完全没有必要等待线程启动this_thread::sleep_for()
-适当的同步也可以解决该问题,因此您只需删除该行即可。 Note this is pretty inefficient way of doing proper multithreading - there should be thread pool instead of individual object with separate mutex and condition variable each. 请注意,这是进行正确的多线程处理的效率非常低的方法-应该有线程池,而不是每个对象都有单独的互斥量和条件变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.