You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

特殊条件下std::map<int, std::atomic<T>>是否线程安全?

问题

通常情况下,多线程并发访问同一个std::map实例是线程不安全的。请问在同时满足以下两个特殊条件时,对该std::map的并发访问是否可以保证线程安全:

  • std::map实例完成初始化流程后,不再执行任何元素插入、删除操作,map的内部结构保持固定不变;
  • std::map存储的value类型为std::atomic<T>。
回答

满足上述两个条件时,对该std::map的并发访问是线程安全的,依据如下:

  1. 从C++标准库的容器线程安全规则来看:只要不存在修改容器本身内部结构的操作(包括插入、删除元素、触发内部重排/重平衡的操作等),多线程并发对容器执行只读访问(包括find查找、遍历已有节点、读取已有元素的key等)不存在数据竞争,属于标准定义的安全行为。第一个条件已经完全排除了容器结构修改的可能,所有调用的find方法都只是遍历map固定的红黑树结构、定位目标节点,全程不会修改容器的任何内部状态,不会触发容器层面的并发冲突。
  2. 对节点value的并发访问安全性由std::atomic保证:std::atomic<T>类型的读写操作本身是原子的,默认内存顺序即可避免多线程下读写value产生的数据竞争,不会出现未定义行为。第二个条件刚好覆盖了value层面的并发访问场景,不存在对非原子变量的并发写/读写冲突。

使用-fsanitize=thread选项编译对应测试代码时,ThreadSanitizer(业内通用的线程数据竞争检测工具)未检测到任何线程安全问题,也验证了该场景的安全性。

可运行测试代码
#include<atomic>
#include<thread>
#include<map>
#include<vector>
#include<iostream>
#include<chrono>

class Demo{
public:
Demo()
{
    mp_.insert(std::make_pair(1, true));
    mp_.insert(std::make_pair(2, true));
    mp_.insert(std::make_pair(3, true));
}

int Get(const int& integer, bool& flag)
{
    const auto itr = mp_.find(integer);
    if( itr == mp_.end())
    {
        return -1;
    }
    else
    {
        flag = itr->second;
        return 0;
    }
}
int Set(const int& integer, const bool& flag)
{
    const auto itr = mp_.find(integer);
    if( itr == mp_.end())
    {
        return -1;
    }
    else
    {
        itr->second = flag;
        return 0;
    }
}

private:
std::map<int, std::atomic<bool>> mp_;
};

int main()
{
    Demo demo;

    std::vector<std::thread> vec;

    vec.push_back(std::thread([&demo](){
        while(true)
        {
            for(int i=0; i<9; i++)
            {
                bool cur_flag = false;
                if(demo.Get(i, cur_flag) == 0)
                {
                    demo.Set(i, !cur_flag);
                }
                std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            }
        }
    }));

    vec.push_back(std::thread([&demo](){
        while(true)
        {
            for(int i=0; i<9; i++)
            {
                bool cur_flag = false;
                if(demo.Get(i, cur_flag)==0)
                {
                    std::cout << "(" << i << "," << cur_flag <<")" << std::endl;
                }
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
    })
    );

    for(auto& thread:vec)
    {
        thread.join();
    }
}

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:21:28