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

strange behaviour when using mutex in C++

本文关键字:C++      更新时间:2023-10-16

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

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

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

正如您所看到的,互斥被用来锁定增量操作(效率低下,我知道正确的解决方案是使用原子,但我正在努力了解发生了什么)。

这段代码在两个线程中运行,值为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 nn";
    auto test = LockedIncrement(nofIncrements);
    test.DoTest();
}

gist中的代码增加了未初始化的_counter,这导致了不确定的行为。你很幸运得到200000和200001…我得到377232…

LockedIncrement(int nofIncrements) : 
    _nofIncrements( nofIncrements ), 
    _counter ( 0 )
{
}
相关文章:
  • 没有找到相关文章