无法从分离的线程访问 C++ unordered_map 中的键值对
Posted
技术标签:
【中文标题】无法从分离的线程访问 C++ unordered_map 中的键值对【英文标题】:Cannot access key-value pair in a C++ unordered_map from a detached thread 【发布时间】:2016-01-13 06:22:44 【问题描述】:我是一名 Java 开发人员,只使用 C++ 编写了一个星期,所以请放轻松 :-)
我有一些代码在其中分离了一个线程,我需要使用该线程将消息发送到注册的服务器。该线程包含在单例 UpdateService 中,其中 unordered_map 作为成员变量。问题是我的键值对在添加到 unordered_map 后丢失了。
构造函数和单例实例化:
UpdateService& UpdateService::getInstance()
static UpdateService onlyInstance;
return onlyInstance;
UpdateService::UpdateService()
std::thread t(&UpdateService::pollForUpdates, this);
t.detach();
投票更新:
void UpdateService::pollForUpdates()
while (true)
std::cout << "UpdateService 33 " << m_client_registrations.size() << "\n";
std::unordered_map<std::string, ServerStub>::iterator iterator = m_client_registrations.begin();
if ( iterator != m_client_registrations.end())
std::string clientId = iterator->first;
std::cout << "UpdateService 38 " << clientId << "\n";
sendUpdate(clientId);
std::this_thread::sleep_for (std::chrono::seconds(1));
我的 UpdateService 启用注册:
void UpdateService::registerForUpdates(std::string clientId, ServerStub server)
if ( nullptr == getServer(clientId) )
std::pair<std::string, ServerStub> pair (clientId, server);
m_client_registrations.insert(pair);
std::cout << "UpdateService 71 " << m_client_registrations.size() << "\n";
std::cout << "UpdateService 74 " << m_client_registrations.size() << "\n";
我通过这样的 Main 方法设置对象:
//initialise the update service and server stub
UpdateService service = UpdateService::getInstance();
ServerStub server = ServerStub();
service.registerForUpdates("clientId0", server);
控制台输出如下所示:
UpdateService 33 0
--> server is being registered here
UpdateService 71 1
UpdateService 74 1
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
UpdateService 33 0
任何人都可以向我建议这里可能发生的事情吗? map 是一个成员变量,在我的头文件 std::unordered_map m_client_registrations 中定义;
我也非常有兴趣了解我应该如何调试它并自己解决它,我已经陷入了深渊,周围没有 C++ 开发人员来帮助我。我正在使用 Visual Studio Express 2012。
非常感谢!
【问题讨论】:
您运行的是优化的发布版本还是未优化的调试版本?优化器可以优化您的pollForUpdates
函数,并且只从 m_clientRegistrations
读取一次,因为您的循环中没有任何东西可以改变它。
不确定这是否回答了您的问题,但我正在使用标准 IDE 配置构建解决方案,然后选择本地 Windows 调试器 --> 发布。到目前为止,这对于我需要的东西来说效果很好,但我不知道不同选项之间的细微差别。
【参考方案1】:
您需要锁定以仲裁对地图的访问并在之后同步其内存。在UpdateService
中添加std::mutex
成员,并确保所有线程仅在持有锁时才访问映射,如:
std::lock_guard<std::mutex> lock(m_client_registrations_mutex);
...access or change the m_client_registrations...
// automatic unlock happens as you leave scope
【讨论】:
谢谢,我会试试的。我已经很长时间没有使用线程了,但至少如果程序是用 Java 编写的,我会更有信心。 当我声明 mutex 成员变量时,我得到编译器错误:错误 C2248: 'std::mutex::mutex' : cannot access private member declaration in class 'std::mutex' 更新到上述内容:这似乎与 UpdateService 是单例有关。如果我将复制构造函数设为私有,UpdateService::getInstance();不再编译,因此 getInstance() 必须尝试复制互斥锁。 @PetraUpdateService service = UpdateService::getInstance();
调用正在复制您的实例并创建您看到的行为,因为您有两个单例实例。您想使用引用变量:UpdateService &service = UpdateService::getInstance();
@1201ProgramAlarm 2 非常感谢,这解决了我的问题!以上是关于无法从分离的线程访问 C++ unordered_map 中的键值对的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C++ 中单独锁定 unordered_map 元素
unordered_map 中的 C++ 线程(无复制构造函数)