我已经写了这段代码作为测试:
#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?
最佳答案
这里的问题是您的数据竞争非常小。任何现代编译器 will convert your inc
function to counter += a
,所以比赛窗口非常小 - 我什至会说,一旦你启动第二个线程,第一个线程很可能已经完成。
这不会减少未定义的行为,但会解释您看到的结果。您可能会使编译器对您的循环不那么聪明,例如通过使 a
或 k
或 counter
volatile
;那么您的数据竞争应该变得明显。
关于c++ - std::mutex 使用示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51369661/