我有以下任务要做。我想启动一个线程管理器/池,它应该启动所有线程并等到有工作要做。然后我应该通知线程做什么工作,并且当它完成时我应该收到一个信号。我已经在下面实现了它,但似乎没有用。
class ThreadManager{
public:
std::vector<std::thread> threads;
std::vector<bool> threadCompletes;
std::mutex sendMtx, recvMtx;
std::condition_variable sendCv;
static void thread_worker(int id, ThreadManager* manager){
while(1){
cout << "Thread Wait: " << id << endl;
std::unique_lock<std::mutex> lck(manager->sendMtx);
manager->sendCv.wait(lck);
**lck.unlock();** # JUST ADDED THIS
// DO WORK
std::this_thread::sleep_for(std::chrono::milliseconds(500));
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 << endl;
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(){
for(auto i : threadCompletes) i = 0;
recvMtx.lock();
std::unique_lock<std::mutex> sendLck(sendMtx);
sendCv.notify_all();
}
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<5; i++){
manager.addThread();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
manager.signal();
manager.wait();
cout << "Complete" << endl;
manager.join();
}
线程全部在等待调用时启动并阻塞,当我发出信号时,每个线程似乎只会随后运行。
Thread Wait: 0
Thread Wait: 1
Thread Wait: 2
Thread Wait: 3
Thread Wait: 4
Job Complete: 0
Thread Wait: 0
Job Complete: 1 # Done one after the other 500ms
Thread Wait: 1
Job Complete: 2 # Done one after the other 500ms
Thread Wait: 2
Job Complete: 3 # Done one after the other 500ms
Thread Wait: 3
Job Complete: 4 # Done one after the other 500ms
All Done
Thread Wait: 4
Complete
我做错了什么
修改
我添加了解锁标志。但是,现在如果我做这样的事情,它最终会失败:
for(int i=0; i<10; i++){
manager.signal();
manager.wait();
cout << "Complete" << endl;
}
cout << "ALL DONE" << endl;
基本上,它运行到&#34;完成&#34; 2或3次,但它永远不会达到&#34;全部完成&#34;。还有一些其他竞争条件正在进行中
答案 0 :(得分:0)
每个线程在其生命周期的大部分时间内锁定相同的互斥锁,包括大约500ms的睡眠操作,该操作只能在线程获得互斥锁后开始。这有效地防止了并发性并使多线程无用。
我根本不了解在工作线程中进行睡眠的目的,但如果有,则将其移动到互斥锁之外。一旦条件变量被唤醒就通过解锁来做到这一点;你不再需要它了;这将释放其他线程以便同时工作。