【问题标题】:C++11 : Using local static variables in multithreaded program caused coredumpC++11:在多线程程序中使用局部静态变量导致 coredump
【发布时间】:2021-12-28 06:55:49
【问题描述】:

在C++11中,我创建了100个线程,每个线程调用Test::PushFunc,添加局部静态变量index,插入到局部集合变量本地地图

理论上,index存储在Initialized Data Segment Memory中,并在程序运行时由每个线程添加。 下面一行

assert(it == localMap.end());

是合理的,因为 index 插入到 localMap 中不会重复。

但实际上,程序在断言中是随机转储的。你能告诉我为什么吗?谢谢。

#include <set>
#include <iostream>
#include <thread>
class Test {
public:
    std::set<std::string> localMap;
    void PushFunc()
    {
        static uint64_t index = 0;
        while (true) {
            std::cout << "index : " << index << "\n";
            ++index;
            const auto& s = std::to_string(index);
            const auto& it = localMap.find(s);
            assert(it == localMap.end()); //! coredump here
            localMap.insert(s);
            if (index > 20000000) {
                break;
            }
        }
    }
};


int main ()
{
    std::vector<std::thread> processThreads;
    for (int i = 0; i < 100; ++i) {
        processThreads.emplace_back(
                std::thread([]()
                {
                    Test t;
                    t.PushFunc();
                }
                ));
    }
    for(auto& thread : processThreads){
        thread.join();
    }
}

【问题讨论】:

  • 为什么是const auto&amp;
  • @ÖöTiib localMap 不在线程之间共享,只有 index 是。
  • 为什么不能const auto&amp;?每个变量都不会改变可以定义为const

标签: c++ multithreading static-variables


【解决方案1】:

但实际上,程序在断言中是随机转储的。你能告诉我为什么吗?

因为你有一个数据竞争——多个线程试图在没有任何同步的情况下读取和写入同一个变量。

index 是一个全局 变量。您需要使用互斥锁来保护对它的访问。

日期:

但localMap不是全局变量,数据竞争无法解释一个索引重复两次。

  1. 具有数据竞争(未定义行为)的程序可以产生任何结果。
  2. 是的,可以。

考虑以下指令交错(时间递减):

  • T1 将index 加载到寄存器中(比如5)。
  • T2 加载index(再次5
  • T1 将 index 递增到 6,将 "6" 存储到其映射中
  • T1 加载 6,将 index 递增到 7,将 "7" 存储到其映射中
  • T2“增量”索引到6,将"6" 存储到自己的地图中
  • T1 加载 6,将其增加到 7,尝试将 "7" 存储到其映射中 ==> 断言失败!

问题在于index++ 不是原子 操作,并且(没有互斥体)其他线程可能会干扰它。

【讨论】:

  • 但是localMap不是全局变量,数据竞争无法解释一个index重复两次。
  • @ArmStrong 你错了。我已经更新了答案。
  • @ArmStrong 您正在通过++index 在多个线程中更新index。一个线程可以多次观察到相同的值(最多2500次)。
  • @EmployedRussian 非常感谢。你的解释很清楚。
猜你喜欢
  • 1970-01-01
  • 2012-08-16
  • 2011-06-03
  • 2016-04-24
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 2015-10-15
相关资源
最近更新 更多