无法从分离的线程访问 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() 必须尝试复制互斥锁。 @Petra UpdateService service = UpdateService::getInstance(); 调用正在复制您的实例并创建您看到的行为,因为您有两个单例实例。您想使用引用变量:UpdateService &amp;service = UpdateService::getInstance(); @1201ProgramAlarm 2 非常感谢,这解决了我的问题!

以上是关于无法从分离的线程访问 C++ unordered_map 中的键值对的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中单独锁定 unordered_map 元素

unordered_map 中的 C++ 线程(无复制构造函数)

与 C++ unordered_map 的并行性

如何在 C++ 中的 unordered_map 的并发读取和锁定单线程写入之间交替

无法永远分离线程c ++

在 C++ 中从 unordered_map 访问值