c++ - std::mutex 使用示例

标签 c++ multithreading mutex data-race

我已经写了这段代码作为测试:

#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 个线程 ab,我希望找到数据竞争。输出是 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 ,所以比赛窗口非常小 - 我什至会说,一旦你启动第二个线程,第一个线程很可能已经完成。

这不会减少未定义的行为,但会解释您看到的结果。您可能会使编译器对您的循环不那么聪明,例如通过使 akcounter volatile;那么您的数据竞争应该变得明显。

关于c++ - std::mutex 使用示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51369661/

相关文章:

c++ - 从输入流中读取具有跳过 block 能力的行

C++继承问题

c++ - 将对成员的引用传递给基类的构造函数

条件变量与信号量示例

java - 线程还是单独的对象实例?

java - 使用java中的synchronous关键字安全访问成员变量

go - 在锁定之前推迟解锁是否可以

c++ - 字符串解码 : looking for a better approach

java - java中锁机制的实现查询

c++ - C++ std::lock_guard作用域范围