[英]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.