3

对非同步的并发更新HashMap显然会导致活锁或其他数据损坏;为避免这种情况,应使用并发版本或实施同步机制。

对HashMap.get()的并发调用可以改变 HashMap 的状态,比如重新散列吗?

更新:

一些评论者想知道这个问题的实际方面,除了吹毛求疵的数据结构行为的理论乐趣。

如果get()不改变状态HashMap(并且不能因为另一个原因导致活锁),那么单个线程可以提前创建一个HashMap,然后多个线程可以同时读取它。如果并发读取不安全,我们需要ConcurrentHashMap对每个多线程访问,无论类型如何。

4

4 回答 4

4

来自java 文档

如果多个线程同时访问一个哈希图,并且至少有一个线程在结构上修改了该图,则必须在外部进行同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)

这意味着并发get()很好,不会导致状态变化。

此外,您始终可以查看源代码以获取有关其构建方式的更多信息。

于 2012-11-14T07:48:04.007 回答
1

Javadocs 通常定义什么是地图的结构修改。HashMap 声明这get不是会导致结构修改的操作。

但是,其他地图实现的行为不同。例如,LinkedHashMap可以使用访问顺序,在这种情况下get是结构修改:

在按访问顺序链接的哈希映射中,仅使用 get 查询映射是一种结构修改。

于 2012-11-14T07:45:24.907 回答
0

如果你知道里面发生了什么HashMap.get()(这是Map接口的具体实现),你可以阅读实现的代码。

但是出于所有目的,您不应该关心该功能是如何实现的以及它的作用!唯一重要的是函数自己实现它的契约(API + 类/函数 javadocs)。未来的实现可能会发生变化,因此依赖它是不好的做法。

于 2012-11-14T07:45:44.070 回答
0

正如你所说,只有打电话get()肯定不会造成任何问题。但是,并发的非同步更新肯定会导致这种情况。在get()方法中,它只会在找到匹配项之前调用hashcode()成员的方法。在这种情况下不会进行更新。

于 2012-11-14T07:51:28.427 回答