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

我在一个HashMap上从多个线程使用.get(…)、. put(…)和.clear()操作. .put(…)和.clear()在同步块内,但.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(…)操作放入synced(map)块中会出什么问题或会改善什么.

解决方法:

这是一个简单的方案,它将在不同步的get上产生问题:

>线程A开始获取,计算哈希桶数,并被抢占
>线程B调用clear(),因此分配了较小的存储桶数组
>线程A唤醒,并且可能会遇到index-out-of-bounds异常

这是一个更复杂的方案:

>线程A锁定地图以进行更新,并被抢占
>线程B启动get操作,计算哈希桶数,并被抢占
>线程A唤醒,并继续放置,并意识到需要调整大小的存储桶
>线程A分配新的存储桶,将旧内容复制到其中,并添加新的存储桶
>线程B唤醒,并在新的存储桶阵列上使用旧的存储桶索引继续搜索.

此时,A可能不会找到正确的项目,因为它很可能位于不同索引的哈希存储桶中.这就是为什么get也需要同步的原因.

上一篇:Python在开发实时嵌入式系统中的作用


下一篇:基于嵌入式系统的机器视觉技术简析