死锁c ++线程条件变量

时间:2018-02-11 08:55:47

标签: c++ multithreading mutex deadlock

我有一个名为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为true
for(;!endWork;);  

然而,这个在stopWork方法中很好用:

endWork=true;

如果我更换

  for(;!endWork;); 

通过

for(;!endWork;){printf("work\n");}

该计划运作良好! 我的错误是什么?

我期待您的回复。

1 个答案:

答案 0 :(得分:0)

  

for(;!endWork;){printf("work\n");}该计划运作良好!我的错误是什么?

由于变量endWork是常规变量,具有高优化选项(即-O3)的编译器可能会假设变量不会更改并优化循环内的读取,即它会转换循环:

for( ; !endWork; ) ;

if(!endWork) for (;;) ;

使用printf()时会发生太多事情,因此编译器无法确定我们是否在endWork内更改printf()变量。因此,它不会如上所示优化循环。

如何处理这个问题?最简单的方法是将endWork声明为volatile。这将为编译提供一个提示,值endWork可能会在其他地方(即另一个线程)更改,因此它不会如上所示优化循环。

相关问题