我正在尝试为一个对象设计消息队列。有一组X个线程,它们都可以向该对象发送消息(稍后处理)。如果我有一个std :: map<thread_id_t,message>
,假设线程1仅添加具有键1的消息,线程2添加具有键2的消息等等,那么这是线程安全的吗?
我正在尝试为一个对象设计消息队列。有一组X个线程,它们都可以向该对象发送消息(稍后处理)。如果我有一个std :: map<thread_id_t,message>
,假设线程1仅添加具有键1的消息,线程2添加具有键2的消息等等,那么这是线程安全的吗?
std::map
不支持多个同时写入。这是STL maps不支持线程安全的许多原因中的一种。STL map的底层实现是AVL树,在插入一定数量的元素后需要重新平衡。重新平衡会影响多个节点,绝对不是线程安全的。
如果您对此感兴趣,请参考优秀的关于无锁数据结构的Dr. Dobb文章。
std::vector<std::vector<message>>
,其中每个线程 ID 都被映射到外部向量中的一个索引,会是一个更好的想法吗? - Sam Kellettconst
方法(除了一些方法,如std::vector<T>::operator[]()
),则不能让任何其他线程以任何方式同时访问此对象。如果需要使用这些操作,则需要在不同线程之间同步访问。标准中相关的条款是17.6.4.10 [res.on.objects]第1段:
如果来自不同线程的对标准库函数的调用可能引入数据竞争,则程序的行为未定义。可能出现这种情况的条件在17.6.5.9中指定。
...和17.6.5.9 [res.on.data.races]描述了标准C++库不允许在没有调用非const
成员函数的情况下改变对象。
由于将对象插入std::map<...>
显然是非const
操作,因此在没有同步的情况下不能同时从多个线程进行插入操作。