【发布时间】:2018-07-16 20:28:56
【问题描述】:
我已经写了这段代码作为测试:
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
auto inc(int a) {
for (int k = 0; k < a; ++k)
++counter;
}
int main() {
auto a = std::thread{ inc, 100000 };
auto b = std::thread{ inc, 100000 };
a.join();
b.join();
std::cout << counter;
return 0;
}
counter 变量是全局变量,因此,创建 2 个线程 a 和 b,我希望找到数据竞争。输出是 200000 而不是随机数。为什么?
此代码是使用mutex 的固定版本,因此全局变量只能访问一次(每次1 个线程)。结果还是200000。
std::mutex mutex;
auto inc(int a) {
mutex.lock();
for (int k = 0; k < a; ++k)
++counter;
mutex.unlock();
}
事实是这样的。互斥体解决方案给了我 200000 这是正确的,因为一次只有 1 个威胁可以访问计数器。但是为什么非互斥解决方案仍然显示200000?
【问题讨论】:
-
行为未定义,它可以做任何事情,包括给出你期望的结果。它可能不在另一个平台上、另一个平台上或以后。也许增量运算符在您的平台上是原子的?
-
对于这个应用程序,你可以使用
std::atomic<int> counter;。看来您的平台具有原子int增量。std::atomic<int>可以便携地利用这一点。 -
@FrançoisAndrieux 我使用 VS2017 和英特尔 i7700k。我的平台没有原子增量操作!我用 Delphi 编写了相同的代码,非互斥体给了我随机值
-
如果您坚持推测未定义的行为,您需要分享使用的确切编译器版本和编译标志。
-
即使除了未定义的行为问题,即使在
-O1,gcc 和 clang 都将您的函数实现为单个add指令......所以你不太可能看到这些冲突...... .
标签: c++ multithreading mutex data-race