【问题标题】:What operations are thread-safe on std::map?std::map 上的哪些操作是线程安全的?
【发布时间】:2011-01-11 08:22:47
【问题描述】:

假设我有:

stl::map<std::string, Foo> myMap;

下面的函数线程安全吗?

myMap["xyz"] ?

即我想要这个在许多线程之间共享的巨大只读映射;但我不知道即使搜索它是否是线程安全的。


一切都先写入一次。

然后,多个线程从中读取。

我正在尝试避免使用锁,以使其尽可能快。 (yaya 可能过早的优化我知道)

【问题讨论】:

    标签: c++ multithreading dictionary std c++-standard-library


    【解决方案1】:

    C++11 要求声明为 const 的所有成员函数对于多个读取器都是线程安全的。

    调用myMap["xyz"] 不是线程安全的,因为std::map::operator[] 未声明为const。 调用myMap.at("xyz") 是线程安全的,因为std::map::at 被声明为const

    【讨论】:

      【解决方案2】:

      理论上没有 STL 容器是线程安全的。实际上,如果容器没有被同时修改,那么读取是安全的。即标准没有关于螺纹的规范。该标准的下一个版本将和 IIUC 将保证安全的只读行为。

      如果您真的很担心,请使用带二分查找的排序数组。

      【讨论】:

        【解决方案3】:

        至少在 Microsoft 的实现中,从容器中读取是线程安全的 (reference)。

        但是,std::map::operator[] 可以修改数据并且未声明为const。您应该改用 std::map::find(即 const)来获取 const_iterator 并取消引用它。

        【讨论】:

        • 为了让容器中有任何东西,它需要被写入。因此,线程安全问题......
        • 问题指定我们正在查看只读地图。我认为这意味着它在从多个线程读取之前完全填充在一个线程中。
        【解决方案4】:

        理论上,只读数据结构和函数不需要任何锁来保证线程安全。它本质上是线程安全的。并发内存读取没有数据竞争。但是,您必须保证仅由单个线程进行安全初始化。

        正如 Max S. 所指出的,大多数情况下,读取 map 中的元素(如 myMap["xyz"])没有写入操作。如果是这样,那么它是安全的。但是,再一次,你必须保证除了初始化阶段之外没有线程修改结构。

        【讨论】:

          【解决方案5】:

          STL 集合不是线程安全的,但将线程安全添加到其中相当简单。

          最好的办法是围绕相关集合创建一个线程安全的包装器。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-23
            • 2012-04-18
            • 2011-11-04
            • 1970-01-01
            • 2013-02-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多