簡體   English   中英

為什么在更改操作同步時需要同步HashMap.get(key)?

[英]Why does HashMap.get(key) needs to be synchronized when change operations are synchronized?

我在一個HashMap上使用來自多個線程的.get(...) .put(...).clear()操作。 .put(...).clear()synchronized塊內,但.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();
}

由於synchronized和get(...)返回null或實例,寫操作將使緩存無效。 通過將.get(...)操作放入synchronized(map)塊,我無法真正看出會出現什么問題或者會有什么改進。

這是一個簡單的場景,會在非同步的get上產生問題:

  • 線程A開始get ,計算哈希桶號,並獲得搶占
  • 線程B調用clear() ,因此分配較小的桶數組
  • 線程A醒來,可能會遇到索引越界異常

這是一個更復雜的場景:

  • 線程A鎖定地圖以進行更新,並獲得搶占
  • 線程B啟動get操作,計算哈希桶號,並獲得搶占
  • 線程A喚醒並繼續put ,並意識到存儲桶需要調整大小
  • 線程A分配新存儲桶,將舊內容復制到其中,然后添加新項目
  • 線程B喚醒,並使用新數據桶陣列上的舊存儲桶索引繼續搜索。

此時,A可能不會找到正確的項目,因為它很可能位於不同索引的哈希桶中。 這就是為什么get需要一並同步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM