std::map 访问线程是不是安全,如果它的迭代器永远不会失效
Posted
技术标签:
【中文标题】std::map 访问线程是不是安全,如果它的迭代器永远不会失效【英文标题】:Is std::map access thread safe if iterators to it are never invalidatedstd::map 访问线程是否安全,如果它的迭代器永远不会失效 【发布时间】:2019-03-07 02:18:02 【问题描述】:所以我想生成这样的地图:std::map<std::string, std::atomic<bool>>
。我的用例是一些运行时检查,以查看是否满足某些条件(真或假);我在这张地图中缓存了条件检查的结果,因为这些检查很昂贵。
我的想法是我使用std::call_once
预先填充此地图,然后不再删除或插入元素。但是,我可以通过 find() 并发访问它,这些访问可能会使用 store(true) 更改 std::atomic
值的值。
现在我想知道这是否是线程安全的?我必须承认我觉得我在这里处于未定义的行为领域。
【问题讨论】:
如果您的地图在多个线程开始搜索之前已完全构建,那就没问题了。 请注意,[]
运算符可能会修改地图,因此如果使用它,所有赌注都将被取消。前提是地图从不修改,这是安全的;确保它安全的最好方法是确保如果没有发生编译错误。这可以很容易地确保地图在构建后始终为const
。确保它的最佳方法是使其成为const
类成员,并在类的构造函数的初始化部分中完全创建它。这将证明映射始终是 const 的,不能被修改,因此是线程安全的。
@SamVarshavchik 考虑到他们打算修改映射的(原子)值,我认为他们不能让地图为 const。
这可以通过将 map 的值作为一个具有 atomic 标志的类作为可变类成员来解决。
【参考方案1】:
如果对它的迭代器永远不会失效,那么 std::map 访问线程是否安全
这不是充分前提。插入不会使迭代器失效,但会引入与其他访问线程的竞争。
我的想法是我预先填充这张地图
这似乎足够了。只要没有线程修改它,从多个线程并发读取(查找、遍历等)标准映射是安全的。
这些访问可能会改变
std::atomic
的值
访问,甚至写一个原子对象也是线程安全的。但请记住,多个原子操作序列并不是一个整体。
【讨论】:
以上是关于std::map 访问线程是不是安全,如果它的迭代器永远不会失效的主要内容,如果未能解决你的问题,请参考以下文章