【发布时间】:2018-01-02 19:47:43
【问题描述】:
我正在尝试编写一个程序,它使用 c++11 线程功能来生成多个线程,主线程必须等待每个生成的线程完成,并且所有生成的线程必须并行运行。我想出了以下方法:
#include <iostream>
#include <stdio.h>
#include <thread>
#include <condition_variable>
#include <mutex>
using namespace std;
class Producer
{
public:
Producer(int a_id):
m_id(a_id),
m_running(false),
m_ready(false),
m_terminate(false)
{
m_id = a_id;
m_thread = thread(&Producer::run, this);
while (!m_ready) {}
}
~Producer() {
terminate();
m_thread.join();
}
void wait() {
unique_lock<mutex> lock(m_waitForRunFinishMutex);
m_cond.wait(lock);
// avoid spurious wake up
if (m_running) {
wait();
}
lock.unlock();
cout << "wait exit " << m_id << endl;
}
void start() {
m_running = true;
m_cond.notify_all();
}
void terminate() {
start();
m_terminate = true;
}
void run() {
m_ready = true;
do {
unique_lock<mutex> lock(m_mutex);
while (!m_running) {
m_cond.wait(lock);
}
if (!m_terminate) {
cout << "running thread: " << m_id << endl;
}
m_running = false;
m_cond.notify_all();
} while (!m_terminate);
}
private:
int m_id;
bool m_running;
bool m_ready;
bool m_terminate;
thread m_thread;
mutex m_mutex;
mutex m_waitForRunFinishMutex;
condition_variable m_cond;
};
只用一个线程测试时程序运行良好,即以下程序:
int main()
{
Producer producer1(1);
producer1.start();
producer1.wait();
return 0;
}
结果如下:
running thread: 1
wait exit: 1
但是,如果我用 2 个线程测试程序,例如:
int main()
{
Producer producer1(1);
Producer producer2(2);
producer1.start();
producer2.start();
producer1.wait();
producer2.wait();
return 0;
}
我得到以下输出:
running thread: 2
running thread: 1
wait exit 1
似乎 producer2 永远不会收到通知(在producer2.wait()),因此程序永远不会结束。希望有人能指出我在这里缺少的东西。
感谢大家帮助解决问题。最终,问题的根本原因在已接受答案的第 (3) 点中描述。我通过更正wait 函数解决了这个问题,如下所示:
void wait() {
unique_lock<mutex> lock(m_waitForRunFinishMutex);
while (m_running) {
m_cond.wait(lock);
}
lock.unlock();
}
【问题讨论】:
-
不应该
wait()产生死锁吗?因为它被称为递归并且unique_lock<mutex> lock(m_waitForRunFinishMutex)被调用,而m_waitForRunFinishMutex仍然被锁定。 -
一个递归调用从一个方法返回,这意味着 m_waitForRunFinishMutex 在递归调用时被解锁(即因为它超出了范围)。
-
@Gio 你对第一部分有误;递归函数无需展开即可添加到堆栈中。
-
递归调用真的会导致范围离开吗?这是奇怪的行为。不过谢谢。
-
是的,变量离开了作用域,即函数返回。见这里:stackoverflow.com/questions/5852237/…,这意味着 m_waitForRunFinishMutex 在递归调用时被解锁。
标签: c++ multithreading