首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WeakHashMap与并发修改

WeakHashMap与并发修改
EN

Stack Overflow用户
提问于 2018-01-23 21:24:57
回答 4查看 1.5K关注 0票数 3

我正在阅读关于WeakHashMap的Java,我了解基本概念。因为GC线程在后台运行,所以您可以得到“不寻常的行为”,例如迭代时的ConcurrentModificationException等等。

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

对我来说,如果没有同步,那么获得不一致的散列映射的风险就很高。

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

代码语言:javascript
复制
if (map.contains(k)) {
   V v = map.get(k)
}

我是不是遗漏了什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-01-23 21:50:19

您提到的不一致状态问题不会出现,因为GC没有主动地重构WeakHashMaps。当垃圾收集器释放弱引用的引用时,对应的条目不会物理地从映射中删除;条目只是变得陈旧,没有键。稍后,在地图上的其他操作中,条目可能会被实际删除,但GC不会承担此责任。

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

票数 5
EN

Stack Overflow用户

发布于 2018-01-23 21:40:35

您所描述的是文档明确指出的内容:

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

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

特别是,即使您在WeakHashMap实例上同步,并且没有调用它的mutator方法,size方法也有可能随时间返回较小的值,isEmpty方法返回false,然后返回truecontainsKey方法返回true,稍后返回给定键的falseget方法返回给定键的值,但稍后返回null,返回put方法返回null,而remove方法返回以前出现在地图上的密钥,并对键集、值集合和条目集进行连续检查,以依次生成较小数量的元素。

票数 0
EN

Stack Overflow用户

发布于 2018-01-23 21:40:53

这个类主要用于关键对象,其相等方法使用==运算符测试对象标识。一旦这样的键被丢弃,它就永远无法被重新创建,因此不可能在以后的某个时候在WeakHashMap中查找该键,并且对它的条目被删除感到惊讶。

因此,如果对基于身份检查的对象使用WeakHashMap,那么一切都很好。您提到的第一种情况(“GC线程删除某个索引中的某个键,同时在同一索引处,用户线程在数组中插入一个键值对”)。这是不可能的,因为只要用户线程保持对键对象的引用,它就不能被GC丢弃。

第二个例子也是这样:

代码语言:javascript
复制
if (map.contains(k)) {
   V v = map.get(k)
}

您保留引用k,这样就可以访问相应的对象,并且不能丢弃。

这个类将很好地处理不基于对象标识(例如字符串实例)的等于方法的关键对象。然而,对于这样的可重新创建的密钥对象,自动删除其键已被丢弃的WeakHashMap条目可能会令人困惑。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48411077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档