C ++ / boost :: thread程序在join_all之后挂起并从Main返回

时间:2012-11-08 16:46:08

标签: c++ multithreading boost

第一次在这里发帖,但我已经彻底搜索了这个问题的解决方案并且没有解决方案。我有一个类,使用基本上静态范围的线程池计算矩阵的条目。当需要进行新的计算时,静态条件变量会发出信号。当程序结束时,一个静态布尔标志被改变,主线程在退出之前调用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库变量在最后被破坏时会发生问题。有谁能看到这个问题?

1 个答案:

答案 0 :(得分:-1)

根据编译器的优化级别,可以使用以下代码:

while ( curIndex_ < 0 )
            stateChange_.wait( lock );

可以解释为

while ( true )
            stateChange_.wait( lock );

因为变量curIndex_在此while循环内没有改变。这可能会导致您提到的僵局。您可以将curIndex_声明为volatile,以强制编译器不优化对此变量的访问。