簡體   English   中英

Java多線程原子引用賦值

[英]Java multi-threading atomic reference assignment

我有一個緩存,我使用simeple HashMap實現。 喜歡 -

HashMap<String,String> cache = new HashMap<String,String>();

大多數時候使用此緩存來從中讀取值。 我有另一個方法重新加載緩存,在這個方法內部我基本上創建一個新的緩存,然后分配引用。 據我所知,對象引用的賦值是Java中的Atomic。

public class myClass {
     private HashMap<String,String> cache = null;
    public void init() {
       refreshCache();
    }
    // this method can be called occasionally to update the cache.
    public void refreshCache() {
        HashMap<String,String> newcache = new HashMap<String,String>();
       // code to fill up the new cache
       // and then finally
       cache = newcache; //assign the old cache to the new one in Atomic way
    }
}

我理解如果我不將緩存聲明為volatile,其他線程將無法看到更改,但對於我的用例將緩存中的更改傳播到其他線程並且它們可以繼續使用舊緩存並不是時間關鍵延長時間。

你看到任何線程問題嗎? 考慮到許多線程正在從緩存中讀取,並且有時只重新加載緩存。

編輯 - 我的主要困惑是我不必在這里使用AtomicReference,因為賦值操作本身是原子的?

編輯 - 我理解為了使順序正確,我應該將緩存標記為volatile。 但是如果refreshCache方法被標記為synchronized,我不必將緩存設置為volatile,因為Synchronized塊將負責排序和可見性?

它是不是安全沒有正確的內存屏障。

有人會認為在填充緩存的步驟之后會發生緩存(cache = newCache)的分配。 但是,其他線程可能會遭受這些語句的重新排序,因此分配可能在填充緩存之前發生。 因此,可以在完全構造之前獲取新緩存,甚至可以看到ConcurrentModificationException。

您需要強制執行before-before關系以防止此重新排序,並將緩存聲明為volatile將實現此目的。

您應該將緩存標記為volatile

雖然您注意到其他線程可能會“長時間”繼續使用陳舊緩存,但您應該注意到,如果沒有同步邊緣,它們可能會永遠繼續使用陳舊緩存。 這可能不是理想的行為。

按優先順序排列(主要是由於可讀性):

  • 以同步方法更新字段
  • 使用AtomicReference<Map<>>
  • 使用volatile

另見這個問題

那么CopyOnWrite ..集合:

java.util.concurrent.CopyOnWriteArraySet
java.util.concurrent.CopyOnWriteArraySet
and org.apache.mina.util.CopyOnWriteMap

它們在您的情況下可以很好地匹配,並且它們是線程安全的。

似乎沒問題。 確保不會過於頻繁地調用refreshCache或將其標記為已synchronized

暫無
暫無

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

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