递增计数器时避免竞争条件

时间:2012-07-04 21:14:17

标签: c++ multithreading boost boost-thread

我之前已经发布了这个主题,但到目前为止我还没有多少运气。我把它归结为一个不好的问题。这次我做了一个简短的可编辑示例,显示了我试图避免的不良行为。我希望这是值得赞赏的。

问题是两个(或更多)线程被设置为运行相同的进程,并且它们的“id”确定它们操作的变量数据的哪个部分。目前,两个线程都将更新计数器。

当前输出如下所示,

tid = 0, var[tid] = 0
tid = 0, var[tid] = 1
tid = 0, var[tid] = 2
tid = 0, var[tid] = 3
tid = 0, var[tid] = 4
tid = 0, var[tid] = 5
tid = 0, var[tid] = 6
tid = 0, var[tid] = 7
tid = 0, var[tid] = 8
tid = 0, var[tid] = 9
tid = 1, var[tid] = 0
Press any key to continue . . .

所需的输出应该是这样的......

tid = 0, var[tid] = 0
tid = 1, var[tid] = 0
tid = 0, var[tid] = 1
tid = 1, var[tid] = 1
tid = 0, var[tid] = 2
tid = 1, var[tid] = 2
tid = 0, var[tid] = 3
tid = 1, var[tid] = 3 etc.

非常感谢任何指导。

编辑:我已经使用符合预期的代码更新了答案。

[注意效率在这里很重要,我希望尽快完成这个过程]

#include <iostream>  
#include <boost/thread.hpp>

int var[2];
int mT;
int mTotalSamples;
boost::mutex mCountMutex;
boost::thread *threadMap[2];

using namespace std;

void process()
{
    int tid = 1;

    // sleep for 1 seconds - just to make sure threadMap 
    // has been assigned (only ncessary for this demo).
    boost::this_thread::sleep(boost::posix_time::seconds(1));

    if (threadMap[0]->get_id() == boost::this_thread::get_id()){ tid = 0;}

    while ( mT < mTotalSamples ) 
    {
        // perform processing
        var[tid] = mT; 
        // processing complete

        mCountMutex.lock(); // (a thread waits to aquire mutex)
        cout << "tid = " << tid << ", var[tid] = " << var[tid] << endl;
        mT++;           // How to stop both threads incrementing this?      
        mCountMutex.unlock();       
    }   
}

int main()
{
    boost::thread_group threads;

    mT = 0;
    mTotalSamples = 10;

    threadMap[0] = threads.create_thread( boost::bind(&process) );
    threadMap[1] = threads.create_thread( boost::bind(&process) );

    threads.join_all();

    return 0;
}

2 个答案:

答案 0 :(得分:1)

根据您的预期输出判断,您希望每次更新后线程都能同步。 boost库提供boost::barrier,如果您在wait中的while循环的开头或结尾放置process,那么应该这样做。

#include <iostream>  
#include <boost/thread.hpp>

int var[2];
int mT;
int mTotalSamples;
boost::mutex mCountMutex;
boost::thread *threadMap[2];
boost::barrier bar(2);

using namespace std;

void process()
{
    int tid = 1;        

    // sleep for 2 seconds - just to make sure threadMap 
    // has been assigned (only ncessary for this demo).
    boost::this_thread::sleep(boost::posix_time::seconds(2));

    if (threadMap[0]->get_id() == boost::this_thread::get_id()){ tid = 0;}

    while ( mT < mTotalSamples ) 
    {
        // perform processing
        var[tid] = mT; 
        // processing complete


        bar.wait();
        if (threadMap[0]->get_id() == boost::this_thread::get_id())
        {
            mT++;               
            cout << "var[0] = " << var[0] << endl;
            cout << "var[1] = " << var[1] << endl;                      
        }           
        bar.wait();
    }   
}

int main()
{
    boost::thread_group threads;

    mT = 0;
    mTotalSamples = 10;

    threadMap[0] = threads.create_thread( boost::bind(&process) );
    threadMap[1] = threads.create_thread( boost::bind(&process) );

    threads.join_all();

    return 0;
}

答案 1 :(得分:1)

在进程中使int mT;本地化() - 不是全局的。 或者你需要一个int mT[2]; 那你就不需要互斥。