【问题标题】:Why does this code not create a race-condition?为什么这段代码不创建竞争条件?
【发布时间】:2019-12-29 01:10:19
【问题描述】:

我的问题是,在阅读有关线程的信息时,如果多个线程访问一个变量,就会发生竞争条件。我的直觉是,在这种情况下,我的代码会为“int a”创建一个竞争条件,例如https://en.wikipedia.org/wiki/Race_condition#Example,但它不会发生。我的问题是为什么会这样?

我尝试在一个数组中单独创建多个线程,但没有发生竞态条件。

void increment(int& a) {
    ++a;
}

int main()
{

    int a = 0;

    std::thread pool[100];

    for (auto& t : pool) {
        t = std::thread(increment, std::ref(a));
    }


    for (auto& t : pool) {
        t.join();
    }

    printf("%d", a);

}

我希望只有一些线程实际上会增加“a”并且会发生竞争条件,但我的代码并非如此

【问题讨论】:

  • 未定义行为的有趣之处在于,正确的结果在您可以拥有的结果集中。
  • 您是如何得出不存在竞争条件的结论的?
  • 相关的,如果不是骗子的话:stackoverflow.com/questions/57603868/…
  • 还应注意,编译器甚至可能不会生成与您在 Wikipedia 上比较的示例完全相同的指令,因此您不应该只寻找 a == 1 来检测比赛。即使a == 2,您正在看到竞争条件;你怎么知道哪个线程首先增加了a

标签: c++ multithreading c++11 race-condition


【解决方案1】:

确实如此。

你还没有看到它的任何症状,纯属偶然。

(我希望一次创建和存储一个线程比增量本身慢得多,所以当您进入下一个线程时,从最后一个线程开始的增量通常是 已经完成了。但你不能保证这一点,这是典型的竞争条件。)

您应该/必须以原子方式递增a,或将其与互斥锁同步。

【讨论】:

    【解决方案2】:

    这是不幸的未定义行为的完美示例。

    它只是愚弄你所期望的结果,你永远不知道它会在何时何地击中你的脸。

    为防止它,您必须使用atomics 或使用mutex

    【讨论】:

      【解决方案3】:

      您可以添加调试消息以打印线程号和增量函数的值。 如果增量是按照线程号的顺序,那么就没有竞争条件。

      还有一点:你对竞态条件有什么期望,这只是增加内存位置的值。不是会导致死锁的数据库

      【讨论】:

      • “如果增量是按照线程号的顺序,那么就没有竞争条件。” 不,这只是另一个竞争条件。您不得依赖此类结果。
      • “你对竞态条件的期望是什么,这只是增加内存位置的值。它不是一个会导致死锁条件的数据库” ,不正确。您似乎不了解这些操作的工作原理。增量不是原子的。在这个简单的程序中已经有一个竞争条件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多