【发布时间】:2018-07-28 11:25:36
【问题描述】:
我正在尝试编写一个线程池/管理器,它可以向线程发出信号以执行大量工作,然后在完成后获得回调。不幸的是,如果我调用信号并等待几百次,它最终会失败。下面是实现:
class ThreadManager{
public:
std::vector<std::thread> threads;
std::vector<bool> threadCompletes;
std::mutex sendMtx, recvMtx, boolLock;
std::condition_variable sendCv;
static std::string printBool(std::vector<bool>& bools){
std::string xx;
for(int i=0; i<bools.size(); i++){
if(bools[i]) xx += "1"; else xx+="0";
}
return xx;
}
static void thread_worker(int id, ThreadManager* manager){
while(1){
std::unique_lock<std::mutex> lck(manager->sendMtx);
//cout << "Thread Wait: " << id << endl;
manager->sendCv.wait(lck);
lck.unlock();
// DO WORK
//std::this_thread::sleep_for(std::chrono::milliseconds(10));
manager->boolLock.lock();
cout << "Start ParOp..: " << id << endl;
manager->boolLock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
manager->boolLock.lock();
manager->threadCompletes[id] = true;
bool done = (std::find(std::begin(manager->threadCompletes), std::end(manager->threadCompletes), false) == std::end(manager->threadCompletes));
cout << "Job Complete: " << id << " " << printBool(manager->threadCompletes) << endl;
manager->boolLock.unlock();
if(done){
cout << "All Done" << endl;
manager->recvMtx.unlock();
}
}
}
ThreadManager(){
}
void addThread(){
threadCompletes.push_back(false);
threads.push_back(std::thread(ThreadManager::thread_worker, threads.size(), this));
}
void signal(){
boolLock.lock();
for(auto i : threadCompletes) i = 0;
boolLock.unlock();
recvMtx.lock();
std::unique_lock<std::mutex> sendLck(sendMtx);
sendCv.notify_all();
sendLck.unlock();
}
void wait(){
recvMtx.lock();
recvMtx.unlock();
}
void join(){
for (int i = 0; i < threads.size(); ++i) {
threads[i].join();
}
}
};
void test2(){
ThreadManager manager;
for(int i=0; i<8; i++){
manager.addThread();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
for(int i=0; i<500; i++){
manager.signal();
manager.wait();
cout << "\nComplete: " << i << endl;
}
cout << "ALL DONE" << endl;
manager.join();
}
从代码中可以看出,我尝试循环 signal() 和 wait() 500 次。通常在某个随机点,其中一个线程将无法接收到等待信号,它将永远阻塞,从而导致代码失败。这是输出:
Complete: 68
Start ParOp..: 0
Start ParOp..: 2
Start ParOp..: 1
Start ParOp..: 6
Start ParOp..: 3
Start ParOp..: 7
Start ParOp..: 4
Start ParOp..: 5
Job Complete: 0 10000000
Job Complete: 2 10100000
Job Complete: 1 11100000
Job Complete: 6 11100010
Job Complete: 7 11100011
Job Complete: 3 11110011
Job Complete: 4 11111011
Job Complete: 5 11111111
All Done
Complete: 69
Start ParOp..: 0
Start ParOp..: 2
Start ParOp..: 1
Start ParOp..: 6
Start ParOp..: 7
Start ParOp..: 3
Start ParOp..: 4
Job Complete: 0 10000000
Job Complete: 2 10100000
Job Complete: 1 11100000
Job Complete: 7 11100001
Job Complete: 4 11101001
Job Complete: 3 11111001
Job Complete: 6 11111011
如您所见,循环 68 成功,但循环 69 失败,因为线程 5 未能接收到信号,并且永远阻塞等待。为什么会这样
【问题讨论】:
-
我认为问题是我无法找到一种方法让所有线程在我再次发出信号之前等待,我该怎么做
标签: multithreading c++11