在研究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();
}
答案 0 :(得分:4)
来自gist的代码增量_counter
未初始化,这导致未确定的行为。你很幸运得到200000和200001 ......我得到377232 ......
LockedIncrement(int nofIncrements) :
_nofIncrements( nofIncrements ),
_counter ( 0 )
{
}