我有一个名为Workers的类有问题。
Workers::Workers(int _nbThreads):
goWork(false),
progressWork(false),
endWork(false),
endFinishedWork(false),
nbThreads(_nbThreads)
{
for(int i=0;i<nbThreads;i++){
threads.push_back(new std::thread(&Workers::threadsExecute,this,i));
}
}
void Workers::threadsExecute(int numThread){
for(;;){
std::unique_lock<std::mutex> uniqueMutexWork(mutexWork);
conditionWorkStarted.wait(uniqueMutexWork, [this] {return goWork==true;});
progressWork=true;
mutexWork.unlock();
conditionWorkProgress.notify_all();
for(;!endWork;);
mutexWork.lock();
endFinishedWork=true;
mutexWork.unlock();
conditionWorkFinished.notify_all();
break;
}
}
void Workers::threadsEnd(){
for(int i=0;i<nbThreads;i++){
threads[i]->join();
}
}
void Workers::startWork(int numThread){
std::unique_lock<std::mutex> uniqueMutexWork(mutexWork);
goWork=true;
conditionWorkStarted.notify_all();
conditionWorkProgress.wait(uniqueMutexWork, [this] {return progressWork==true;});
}
void Workers::stopWork(int numThread){
std::unique_lock<std::mutex> uniqueMutexWork(mutexWork);
endWork=true;
conditionWorkFinished.wait(uniqueMutexWork, [this] {return endFinishedWork==true;});
}
主要:
Workers workers* = new Workers(1);//Only one thread worker
workers->startWork(0);
workers->stopWork(0);
问题是在
中永远不会发现变量endWork为truefor(;!endWork;);
然而,这个在stopWork方法中很好用:
endWork=true;
如果我更换
for(;!endWork;);
通过
for(;!endWork;){printf("work\n");}
该计划运作良好! 我的错误是什么?
我期待您的回复。
答案 0 :(得分:0)
for(;!endWork;){printf("work\n");}
该计划运作良好!我的错误是什么?
由于变量endWork
是常规变量,具有高优化选项(即-O3
)的编译器可能会假设变量不会更改并优化循环内的读取,即它会转换循环:
for( ; !endWork; ) ;
到
if(!endWork) for (;;) ;
使用printf()
时会发生太多事情,因此编译器无法确定我们是否在endWork
内更改printf()
变量。因此,它不会如上所示优化循环。
如何处理这个问题?最简单的方法是将endWork
声明为volatile。这将为编译提供一个提示,值endWork
可能会在其他地方(即另一个线程)更改,因此它不会如上所示优化循环。