在C ++中使用互斥锁时的奇怪行为

时间:2014-10-19 19:29:59

标签: c++ multithreading mutex

在研究C ++(11)中关于多线程的一些场景时,我遇到了这种奇怪的(对我来说)情况。

我在2个线程中运行下面的increment函数,传入共享变量的地址。核心代码是:

static std::mutex mtx;

static void increment(int *x, int nofIncrements)
{
    for (int i = 0; i < nofIncrements; i++)
    {
        mtx.lock();
        (*x)++;
        mtx.unlock();
    }
}

正如您所看到的,互斥锁用于锁定增量操作(效率低下,我知道正确的解决方案是使用原子,但我试图了解正在进行的操作)。

此代码在2个线程中运行,其值为nofIncrements = 100000,这意味着我希望最终值为200000。但是,有时我会得到200001,我无法解释......

完整的课程(可在此要点https://gist.github.com/anonymous/4d218dce2a43a06abe6a中找到):

class LockedIncrement
{
    int _nofIncrements;
    int _counter;

    static std::mutex mtx;

    static void increment(int *x, int nofIncrements)
    {
        for (int i = 0; i < nofIncrements; i++)
        {
            mtx.lock();
            (*x)++;
            mtx.unlock();
        }
    }

public:

    LockedIncrement(int nofIncrements)
    {
        _nofIncrements = nofIncrements;
    }

    void DoTest()
    {
        std::thread t1(increment, &_counter, _nofIncrements);
        std::thread t2(increment, &_counter, _nofIncrements);
        t1.join();
        t2.join();
        std::cout << "Counter = " << _counter << " (expected " << 2 * _nofIncrements << ")\n";
    }
};

测试可以像这样运行:

int main(int argc, char* argv[])
{
    auto nofIncrements = 1000000;
    std::cout << "locked increment \n\n";
    auto test = LockedIncrement(nofIncrements);
    test.DoTest();
}

1 个答案:

答案 0 :(得分:4)

来自gist的代码增量_counter未初始化,这导致未确定的行为。你很幸运得到200000和200001 ......我得到377232 ......

LockedIncrement(int nofIncrements) : 
    _nofIncrements( nofIncrements ), 
    _counter ( 0 )
{
}