c++ - 为什么我的线程计数器并不总是完成?

标签 c++ multithreading

我认为我的程序有一个错误,因为有时当我运行程序时,它输出的数字低于 30000,例如 29999。但有时它运行正确并达到 30000。我的问题是如何解决这个问题为什么会这样。

#include <iostream>
#include <thread>

using namespace std;

int counter;
int i;

void increment()
{
counter++;
}

int main()
{
counter = 0;

cout << "The value in counter is : " << counter << endl;
thread tarr[30000];

    for (i = 0; i < 30000; i++)
    {
        tarr[i] = thread(increment);
    }

    for (i = 0; i < 30000; i++)
    {
        tarr[i].join(); //main thread waits for tarr to finish
    }

cout << "After running 30,000 threads ";
cout << "the value in counter is : " << counter << endl;
return 0;
}

最佳答案

问题是 counter++ can be broken down into three operations :

  1. 加载初始值进行注册
  2. 增加值
  3. 将新值存储回内存

单个线程可以执行前两个步骤,然后将控制权传递给另一个线程来执行相同的操作。这可能意味着:

  1. 线程一将 counter 读取为 5
  2. 线程一将其内部拷贝增加到 6
  3. 线程二将 counter 读取为 5
  4. 线程二将其内部拷贝增加到6
  5. 线程将 6 写回 counter
  6. 线程一将 6 写回到 计数器

你应该制作计数器 std::atomic ,或者用 std::mutex 来保护它:

std::atomic<int> counter;

关于c++ - 为什么我的线程计数器并不总是完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43486542/

相关文章:

c++ - 您能否从已编译程序中获取编译器的命令行内容?

java - 执行异步任务的 java 方法的返回值

java - 这个 java .execute() 方法调用是什么意思?

java - 关闭正在队列上读取的守护进程线程

c++ - 使用线程对数组的两半进行排序,但仅对后半部分进行排序

c++ - 如何为模板类的成员结构重载 ostream

c++ - 具有抽象基类的工厂模式 - 通过 ref 或通过值返回?范围界定和切片的问题

c++ - 为什么需要 C++ 头文件的包含保护?

c++ - 在 C++ 中反转数组时,为什么我在输入和输出之间得到一个 "random"数字?

c# - .net-4.6 中的异步 Thread.CurrentThread.CurrentCulture