对于不同的密钥,哈希映射线程是否安全?
如果我有两个多线程访问HashMap,但保证它们永远不会同时访问相同的密钥,这是否仍然会导致争用情况?
如果我有两个多线程访问HashMap,但保证它们永远不会同时访问相同的密钥,这是否仍然会导致争用情况?
在@dotsid的回答中,他是这样说的:
如果您以任何方式更改了 a,那么您的代码就会被破坏。
HashMap
他是对的。在没有同步的情况下更新的 将中断,即使线程使用不相交的键集也是如此。以下是一些可能出错的事情。HashMap
如果一个线程执行 ,则另一个线程可能会看到哈希映射大小的过时值。put
如果一个线程使用与第二个线程的键(当前)位于同一哈希桶中的键执行 a 操作,则第二个线程的映射条目可能会暂时或永久丢失。这取决于哈希链(或其他)的实现方式。put
当一个线程执行触发表重建的 a 时,另一个线程可能会看到哈希表数组引用的瞬态或过时版本、其大小、内容或哈希链。混乱可能会随之而来。put
当线程对某个键执行 a 操作,该键与某个其他线程使用的某个键发生冲突,而后者对其键执行 a 时,后者可能会看到哈希链引用的过时副本。混乱可能会随之而来。put
put
当一个线程使用与某个其他线程的键冲突的键探测表时,它可能会在链上遇到该键。它将在该键上调用 equals,如果线程未同步,则 equals 方法可能会在该键中遇到过时状态。
而且,如果您有两个线程同时执行或请求,则存在许多争用条件的机会。put
remove
我可以想到三种解决方案:
ConcurrentHashMap
HashMap
Lock
HashMap
1 - 我们无法列举所有可能出错的事情。首先,我们无法预测所有JVM将如何处理JMM的未指定方面......在所有平台上。但无论如何,你都不应该依赖这种信息。您需要知道的是,使用这样的HashMap
从根本上是错误的。执行此操作的应用程序已损坏...即使你还没有观察到破碎的症状。
只需使用 ConcurrentHashMap 即可。ConcurrentHashMap使用多个锁,这些锁覆盖了一系列哈希桶,以减少锁被质疑的机会。获得无争议锁具的性能影响很小。
回答你最初的问题:根据javadoc,只要地图的结构不改变,你就可以了。这意味着根本不需要删除元素,也不会添加地图中尚不存在的新键。替换与现有键关联的值是可以的。
如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。
虽然它不保证可见性。因此,您必须愿意偶尔接受检索过时的关联。