当前位置: 首页 > 知识库问答 >
问题:

WeakHashMap与并发修改

晁聪
2023-03-14

我正在阅读关于WeakHashMap的Java文档,我得到了基本概念。由于GC线程在后台运行,因此可能会出现“异常行为”,例如在迭代时出现ConcurrentModificationException等。

我不明白的是,如果默认实现没有同步,并且没有以任何方式包含锁,那么为什么不可能得到不一致的状态呢。假设你有两条线。GC线程在某个索引处删除某个键,同时,在同一索引处,用户线程在数组中插入一个键值对。

对我来说,如果没有同步,那么获取不一致的哈希映射的风险很高。

更糟糕的是,这样做实际上可能非常危险,因为v实际上可能是空的。

if (map.contains(k)) {
   V v = map.get(k)
}

我错过什么了吗?

共有3个答案

亢建木
2023-03-14

指的是

即使您在WeakHashMap[...]上同步,大小方法也可能随着时间的推移返回较小的值

javadoc向我充分解释了存在不一致状态的可能性,并且它完全独立于同步

在后面的几个例子中,也提到了给定的例子:

对于给定的键,该方法返回true,然后返回false

所以基本上,我们不应该依赖WeakHashMap的状态,而应该尽可能地使用它

V v = map.get(k);
if(null != v) {
}

Optional.ofNullable(map.get(k)).ifPresent(() -> { } );
戴博
2023-03-14

您所描述的是文档中明确说明的内容:

因为垃圾回收器可能会在任何时候丢弃密钥,所以WeakHashMap的行为可能就像一个未知线程正在默默地删除条目一样。

你犯的唯一错误就是假设你可以通过同步来保护状态。这不起作用,因为同步在GC方面不是相互的。引用文件:

特别是,即使您在WeakHashMap实例上进行了同步,并且没有调用其任何突变器方法,size方法也可以随着时间的推移返回较小的值,对于isShelty方法,返回false,然后返回true,对于给定键,对于容器键方法,返回true和后来的false,对于get方法,返回给定键的值,但随后返回null,对于put方法,返回null,对于以前在map中出现的键,对于连续检查键集,值集合和条目集,以相继产生较小数量的元素,对于put方法,返回null,对于之前在map中出现的键,以及对于键集,值集合和条目集的连续检查,返回false

颛孙越
2023-03-14

您提到的不一致状态问题不会出现,因为GC没有积极重组WeakHashMaps。当垃圾收集器释放弱引用的referent时,相应的条目不会从映射中物理删除;条目只是变得陈旧,没有密钥。在稍后的某个时刻,在地图上的其他操作中,条目可能会被物理删除,但GC不会承担该责任。

您可以在grepcode上看到这个设计的一个Java版本的实现。

 类似资料:
  • 问题内容: 我正在用Java创建一个多线程聊天。当用户u1向用户u2发送消息但未连接用户u2时,用户u1将消息发送至服务器,而用户u2一旦连接至服务器,便会收到该消息。未发送的消息将添加到ArrayList中。连接用户后,他会检查自己是否是未决邮件的收件人。如果是,则将邮件发送给他,然后将其从待处理邮件列表中删除。这是我的方法: 这就是我得到的: 我如何解决它?是因为我正在使用迭代器吗? 问题答案

  • WeakHashMap是Map接口的一个实现,它只存储对其键的弱引用。 仅存储弱引用允许在其键不再在WeakHashMap之外引用时对键值对进行垃圾收集。 此类提供了利用弱引用功能的最简单方法。 它对于实现“类似注册表”的数据结构很有用,其中当任何线程不再可以访问其密钥时,条目的实用程序就会消失。 WeakHashMap的功能与HashMap相同,但有一个非常重要的例外:如果Java内存管理器不再

  • 问题内容: 我有这段代码,它给了我并发修改异常。即使看不到任何并发修改,我也无法理解为什么继续得到它。 问题答案: 为了避免,你应该这样编写代码: 允许你在迭代期间修改列表,但不能在创建和使用列表之间进行修改。

  • for(条目...)中出现错误循环,其中在调用dfs()之后,它将显示ConcurrentModificationException。虽然visitedOrder与foreach循环不相关,但我不知道为什么会发生这种情况。这怎么修复呢?

  • 编辑 这些更改导致并发mod每次触发而不是断断续续地触发,我想这意味着删除代码更好,但现在错误在触发 线程“awt-eventqueue-0”java.util.concurrentModificatio中的异常nException at java.util.arrayList$itr.checkforcoModification(arrayList.java:901)at java.util.a

  • 我需要一个线程安全的并发列表,同时最适合迭代,并且应该返回精确的大小。我想存储物品的拍卖出价。所以我想能够 检索项目的确切出价数量 为项目添加出价 检索给定项目的所有出价。 移除商品出价 我打算把它放在