【问题标题】:Why does this produce correct output?为什么这会产生正确的输出?
【发布时间】:2013-08-12 13:23:30
【问题描述】:

我只是在写一个多线程/并发教程,下面的代码(我认为)应该不能正常工作,因为 5 个不同的线程在同一个对象上运行。

但它每次都准确地打印出 500 个。这是如何运作的?我没有使用互斥锁,因此无法防止多个线程访问相同的数据...

#include <iostream>
#include <vector>
#include <thread>
using namespace std;

struct Counter {

    int value;

    void increment() {
        value++;
    }
};

int main(){

    Counter counter;
    counter.value = 0;

    vector <thread> threads;

    for (int i = 0; i < 5; i++){
        threads.push_back(thread([&counter](){
            for (int i = 0; i < 100; ++i){
                counter.increment();
            }
        }));
    }


    for (auto& thread : threads)
        thread.join();

    cout << counter.value << endl;

    cin.get();
    return 0;
}

【问题讨论】:

  • 它可以是未定义的行为(可以摆动正确或错误)
  • 我想value++ 语句被编译为一条指令(即它增加内存中的一个值),因此增量不太可能不起作用(即线程 A 读取它,线程 B 读取它,线程 A 写入增量值,线程 B 写入相同的增量值)。
  • 我认为你需要std::packaged_task,而不是std::thread。此外,您还需要互斥锁或其他一些同步对象。
  • 尝试将increment()改为if (value &lt; 50) value+=2;;如果 Drew 是正确的,您可能会更幸运地看到“不正确”的输出。
  • 或者,或者,将counter.value 更改为没有原子增量的类型,例如floatdouble

标签: c++ multithreading mutex


【解决方案1】:

根据编译器的不同,递增 ++i 将产生一条指令,这意味着递增可能会以原子方式执行。

但是,当多个线程在没有任何形式同步的情况下写入同一内​​存时,执行仍会导致数据竞争,并会导致未定义的行为。 UB 意味着几乎任何事情都可能发生,包括显示正确答案。

【讨论】:

    【解决方案2】:

    正如 Snps 所说,多线程处理可能是一种奇怪的野兽,我认为您可以在其中添加一些打印语句,以便您可以检测它在运行时的行为方式。当我遇到与任何线程混淆的东西时,我通常会这样做。

    【讨论】:

      猜你喜欢
      • 2013-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 2020-06-24
      • 2016-06-29
      相关资源
      最近更新 更多