簡體   English   中英

Java多線程原子賦值

[英]Java multi threading atomic assignment

與以下鏈接相同,我對提問者使用相同的代碼。
Java多線程原子引用賦值在我的代碼中,有

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

public class myClass {
    private HashMap<String,String> cache = null;
    public void init() {
       refreshCache();
    }
    // this method can be called occasionally to update the cache.
    //Only one threading will get to this code.

    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
    }

    //Many threads will run this code
    public void getCache(Object key) {
        ob = cache.get(key)
        //do something
    }
}

我一遍又一遍地閱讀 sjlee 的答案,我無法理解在這種情況下這些代碼會出錯。 誰能給我一個例子?
請記住,我不關心 getCache 函數是否會獲取舊數據。
很抱歉,我無法對上述問題添加評論,因為我沒有 50 聲望。 所以我只是添加一個新問題。

如果沒有內存屏障,您可能會看到null或舊地圖,但您可能會看到不完整的地圖。 即你看到它的位,但不是全部。 因此,如果您不介意丟失條目,那么這不是問題,但您可能會看到 Map 對象,而不是它所指的任何內容,從而導致可能的 NPE。

不能保證您會看到完整的地圖。

final字段將可見,但非 final 字段可能不可見。

這是一個非常有趣的問題,它表明你的核心假設之一

“請記住,我並不關心getCache函數是否會獲取舊數據。”

是不正確的。

我們認為,如果“ refreshCache ”和“ getCache ”不同步,那么我們只會得到舊數據,這是不正確的。

初始線程對它們的調用可能永遠不會反映在其他線程中。 由於緩存不是易失性的,每個線程都可以自由地保留它自己的本地副本,並且永遠不會使其跨線程保持一致。

因為多線程的“ visibility ”方面,即除非我們使用適當的鎖定或使用volatile ,否則我們不會觸發發生之前的場景,這會強制線程使共享變量值在它們運行的​​多個處理器之間保持一致on,這意味着“ cache ”,可能永遠不會被初始化,導致在getCache出現明顯的 NPE

要正確理解這一點,我建議閱讀“Java 並發實踐”一書的第 16.2.4 節,該書涉及雙重檢查鎖定代碼中的類似問題。

解決方案:會

  1. 為了使refreshCache同步強制,所有線程在任何一個線程調用它時更新它們的 HashMap 副本,或者
  2. 使cache不穩定或
  3. 你將不得不調用refreshCache在調用每一個線程getCache哪一種失敗的共同緩存的目的。

暫無
暫無

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

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