第一次在这里发帖,但我已经彻底搜索了这个问题的解决方案并且没有解决方案。我有一个类,使用基本上静态范围的线程池计算矩阵的条目。当需要进行新的计算时,静态条件变量会发出信号。当程序结束时,一个静态布尔标志被改变,主线程在退出之前调用join_all。问题是当我从int main()返回时,程序似乎在破坏静态变量期间挂起。
以下是执行计算的类的粗略源代码:
class FunctionCalculator
{
public:
static void createWorkers();
static void destroyWorkers();
static void calcFunction();
private:
static void run();
static boost::thread_group workers_;
static boost::mutex theLock_;
static int curIndex_;
static unsigned int numCalcsComplete_;
static boost::condition_variable stateChange_;
static boost::condition_variable calculationFinished_;
static bool finished_;
static struct SharedCalcData { // some vars } calcData_;
};
// static member definitions
int FunctionCalculator::curIndex_;
unsigned int FunctionCalculator::numCalcsComplete_;
boost::mutex FunctionCalculator::theLock_;
boost::condition_variable FunctionCalculator::stateChange_;
boost::condition_variable FunctionCalculator::calculationFinished_;
boost::thread_group FunctionCalculator::workers_;
bool FunctionCalculator::finished_;
FunctionCalculator::SharedCalcData FunctionCalculator::calcData_;
void FunctionCalculator::createWorkers()
{
finished_ = false;
curIndex_ = -1;
for( unsigned int i = 0; i < 4; i++ )
workers_.create_thread( boost::bind( &FunctionCalculator::run ) );
}
void FunctionCalculator::destroyWorkers()
{
{
boost::mutex::scoped_lock lock( theLock_ );
finished_ = true;
curIndex_ = 0;
stateChange_.notify_all();
}
workers_.join_all();
}
void FunctionCalculator::run()
{
unsigned int i = 0; // the column of the matrix to fill in
while ( true )
{
{
boost::mutex::scoped_lock lock( theLock_ );
// block if the calculation is finished until there's a new calculation
while ( curIndex_ < 0 )
stateChange_.wait( lock );
// check if it's time for threads to die
if ( finished_ )
break;
// get the next index to process
i = (unsigned int)curIndex_++;
// signal all threads to block if this is the last thread in the calculation
if ( i == 49 )
curIndex_ = -1;
}
// perform calculation/fill in matrix
{
boost::mutex::scoped_lock lock( theLock_ );
++numCalcsComplete_;
// wake up the main thread if this was the last thread in the calculation
if ( numCalcsComplete_ == 50 )
calculationFinished_.notify_one();
}
}
}
void FunctionCalculator::calcFunction()
{
// assign calcData_
{
boost::mutex::scoped_lock lock( theLock_ );
curIndex_ = 0;
numCalcsComplete_ = 0;
stateChange_.notify_all();
while ( curIndex_ >= 0 )
calculationFinished_.wait( lock );
}
}
这是主要方法的一些粗略代码。它实际上是一个由main创建的对象,调用createWorkers()和calcFunction()实际上是由Gnu科学库调用的(我出于这个原因使用静态成员),但这个想法是这样的:
int main( int argc, char* argv[] )
{
FunctionCalculator fc;
FunctionCalculator::createWorkers();
for ( int i = 0; i < 10; i++ )
fc.calcFunction();
FunctionCalculator::destroyWorkers();
return EXIT_SUCCESS;
}
在调用EXIT_SUCCESS之后,程序挂起但我已经验证了在调用destroyWorkers()之后,FunctionCalculator中的四个线程已经完成了run()方法。由于程序达到了main的返回,我的理论是当静态boost库变量在最后被破坏时会发生问题。有谁能看到这个问题?
答案 0 :(得分:-1)
根据编译器的优化级别,可以使用以下代码:
while ( curIndex_ < 0 )
stateChange_.wait( lock );
可以解释为
while ( true )
stateChange_.wait( lock );
因为变量curIndex_在此while循环内没有改变。这可能会导致您提到的僵局。您可以将curIndex_声明为volatile,以强制编译器不优化对此变量的访问。