在多线程程序中,我能否使用地图或哈希表而不需要锁定?也就是说,它们是否是线程安全的?
我想同时向地图中添加和删除内容。
似乎有很多相互矛盾的信息。
顺便说一下,我正在使用随Ubuntu 10.04附带的GCC STL库。
编辑:就像互联网上的其他信息一样,我似乎得到了相互矛盾的答案?
在多线程程序中,我能否使用地图或哈希表而不需要锁定?也就是说,它们是否是线程安全的?
我想同时向地图中添加和删除内容。
似乎有很多相互矛盾的信息。
顺便说一下,我正在使用随Ubuntu 10.04附带的GCC STL库。
编辑:就像互联网上的其他信息一样,我似乎得到了相互矛盾的答案?
您可以安全地执行同时读取操作,即调用const成员函数。但如果其中一个涉及写入,即调用非const成员函数,则不能进行任何同时操作,并且容器的非const成员函数调用应该是独占的,不能与任何其他调用混合。
也就是说,您不能从多个线程更改容器。因此,您需要使用锁/读写锁来确保访问的安全性。
不行。
诚实地说,不行。
编辑
好的,我会加以说明。
你可以拥有任意数量的线程读取相同的映射。这是有意义的,因为读取它不会产生任何副作用,所以无论其他人是否也在读取它都没有关系。
然而,如果你想要写入它,那么你需要获得独占访问权,这意味着防止任何其他线程在你完成之前进行写入或读取。
你最初的问题是关于并行添加和删除的。由于这两个操作都是写入操作,所以它们是否线程安全的答案是简单而明确的“不行”。
TBB是一个免费的开源库,提供线程安全的关联容器。(http://www.threadingbuildingblocks.org/)
答案(像大多数线程问题一样)是它大部分时间都能正常工作。不幸的是,如果在地图调整大小时捕获它,那么你将陷入麻烦。所以不行。
为了获得最佳性能,您需要一个多阶段锁。首先是读取锁,允许访问器访问,这些访问器不能修改地图,并且可以由多个线程持有(多个线程读取项目是可以的)。其次是写锁,它是独占的,允许以可能不安全的方式修改地图(添加、删除等)。
编辑 读写锁很好,但它们是否比标准互斥锁更好取决于使用模式。我无法在不知道更多信息的情况下推荐任何一种。对两者进行分析,看哪个最适合您的需求。