我用.get(...)
, .put(...)
and .clear()
多个线程对一个 HashMap 进行操作。.put(...)
and .clear()
都在一个里面synchronized
阻止但是.get(...)
不是。我无法想象这会导致问题,但在我见过的其他代码中.get()
几乎总是同步的。
获取/放置的相关代码
Object value = map.get(key);
if(value == null) {
synchronized (map) {
value = map.get(key); // check again, might have been changed in between
if(value == null) {
map.put(key, new Value(...));
}
}
}
清楚的是:
synchronized (map) {
map.clear();
}
由于同步和同步,写操作将使缓存失效get(...)
返回 null 或实例。我真的看不出什么地方会出问题,或者通过把.get(...)
操作成synchronized(map)
block.
这是一个简单的场景,会在不同步时产生问题get
:
- 线程A启动
get
,计算哈希桶号,并被抢占
- 线程B调用
clear()
,因此分配了较小的桶数组
- 线程A醒来,可能会遇到索引越界异常
这是一个更复杂的场景:
- 线程 A 锁定地图以进行更新,并被抢占
- 线程B发起一个
get
操作,计算哈希桶数,并被抢占
- 线程A醒来,并继续
put
,并意识到存储桶需要调整大小
- 线程 A 分配新的存储桶,将旧内容复制到其中,并添加新项目
- 线程 B 醒来,并使用旧存储桶索引在新存储桶数组上继续搜索。
此时,线程 B 可能无法找到正确的项目,因为它很可能位于不同索引的哈希桶中。因此get
也需要同步。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)