C++无锁实现Map原子访问与修改的问题求助
问题根源分析
你的代码没有执行到set函数里的打印语句,核心原因是原子共享指针未初始化:
Config结构体中的g_config是std::atomic<std::shared_ptr<const ConfigMap>>类型,默认构造后内部的shared_ptr是空指针。- 当
set函数执行std::shared_ptr<const ConfigMap> blue = g_config.load();时,blue是空指针,后续执行std::make_shared<ConfigMap>(*blue)会直接解引用空指针,触发未定义行为(通常表现为程序崩溃退出),因此代码根本没走到打印那一步。
修复方案
1. 初始化原子共享指针
给Config添加构造函数,初始化g_config为指向空ConfigMap的shared_ptr:
Config() : g_config(std::make_shared<const ConfigMap>()) {}
2. 补充缺失的头文件
原代码使用了std::optional但未包含<optional>头文件,这会导致编译错误(部分编译器可能隐式包含,但标准要求显式引入),需要添加:
#include <optional>
修复后的完整代码
#include <iostream> #include <map> #include <string> #include <atomic> #include <memory> #include <optional> #include <thread> struct Config { using ConfigMap = std::map<std::string, std::string>; std::atomic<std::shared_ptr<const ConfigMap>> g_config; // 初始化原子共享指针 Config() : g_config(std::make_shared<const ConfigMap>()) {} void set(const std::string& key, const std::string& value) { std::shared_ptr<const ConfigMap> blue = g_config.load(); std::shared_ptr<ConfigMap> green = std::make_shared<ConfigMap>(*blue); std::cerr << "This is not printing to the console" << std::endl << std::flush; (*green)[key] = value; // 将可修改的shared_ptr转为const版本后存储 g_config.store(std::static_pointer_cast<const ConfigMap>(std::move(green))); } std::optional<std::string> get(const std::string& key) { std::shared_ptr<const ConfigMap> blue = g_config.load(); auto valueIter = blue->find(key); if (valueIter != blue->end()) { return valueIter->second; } return std::nullopt; } }; int main() { std::cout << "Main starting" << std::endl; Config config; std::string key = "default.hostname"; std::string value = "example.com"; std::thread setThread([&config, &key, &value]() { config.set(key, value); std::cout << "Set thread completed" << std::endl; }); setThread.join(); std::optional<std::string> hostnameOpt = config.get("default.hostname"); if (hostnameOpt) { std::cout << "Default Hostname: " << *hostnameOpt << std::endl; } else { std::cout << "Default Hostname not set" << std::endl; } return 0; }
蓝绿模式适配要点(针对单写线程场景)
- 因为你只有一个写入线程,无需处理多写竞争的情况,蓝绿模式的核心逻辑(复制原对象→修改新对象→原子替换指针)可以安全工作。
- 原子
shared_ptr的load和store操作默认使用std::memory_order_seq_cst,这在单写多读场景下足够保证内存可见性,所有读线程能立即看到最新的配置。 - 注意每次修改都要复制整个
map,如果map体积较大,会带来一定的性能开销,这是无锁方案的典型 trade-off。
内容的提问来源于stack exchange,提问作者dopller
相关产品推荐
相关产品推荐

