gpt4 book ai didi

java - 为什么同步变更操作时需要同步HashMap.get(key)?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:42:03 25 4
gpt4 key购买 nike

我使用 .get(...).put(...).clear() 操作来自多个一个 HashMap 上的线程。 .put(...).clear() 位于 synchronized block 内,但 .get(...) 不是。我无法想象这会导致问题,但在我看到的其他代码中 .get() 几乎总是同步的。

get/put的相关代码

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 醒来,并使用新桶数组上的旧桶索引继续搜索。

在这一点上,A 可能不会找到正确的项,因为它很可能位于不同索引处的哈希桶中。这就是 get 也需要同步的原因。

关于java - 为什么同步变更操作时需要同步HashMap.get(key)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32300043/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com