0

有一個快速的同步問題,這裏是我有:法建立之前發生在陣列

一)Class1的已併發的哈希表定義如下:

ConcurrentMap<String, int[][]> map = new ConcurrentHashMap<String, int[][]>(); 

B)的Class2有一個線程,稱爲線程1。 Thread1創建一個Id並檢查地圖是否包含它。如果是,它將檢索值(int [] []),修改內容並將其放回。如果沒有,它會創建一個新的int [] []並存儲它。這個檢查 - >修改/創建的過程經常發生。

private class Thread1 implements Runnable{ 

      public void run(){ 
       //keepRunning is volatile 
       while(keepRunning){ 

        String id  = "ItemA"; 
        int[][] value = map.get(id); 

        //If value is null, create an int[][] and put it back as value for Id 
        //If value is not null, modify the contents according to some logic 
       } 
      } 
    } 

C)最後,我還有一個線程,稱爲線程2。這個線程需要一個id,檢查映射是否有值。如果沒有,沒有任何反應。如果是這樣,那麼它總結int [] []中的值,並使用該數字進行一些計算(此處不作修改)。

我想弄清楚我的操作是否是原子操作。 b)中的操作很好,因爲數組的創建/修改和插入地圖僅限於一個線程(Thread1)。另外,由於插入到映射中會建立一個before-before動作,這將確保c)將在int [] []中看到更新的值。

但是,我不太確定如果Thread2在映射中查找相同的int [] []會發生什麼情況,並嘗試在Thread1修改它時對其進行總結。

我正確地認爲Thread2會在int [] []中看到較舊(但未損壞)的值。原因是在Thread1完成將值放回地圖之前,新的修改不會對Thread2可見。

非常感謝。

+0

正如旁註,你可能知道這是否,但它聽起來像你試圖實施生產者/ Consmer模式,看看http://docs.oracle.com/javase/tutorial/essential/併發/ guardmeth.html一些更多的想法 – MadProgrammer 2012-08-04 04:39:27

回答

1

您的操作不是原子的,線程2將試圖在線程1修改它們時對值進行求和。

爲避免這種情況,您需要複製原始修改副本並放回副本。

+0

嗨湯姆,謝謝。或者,我可不a)使用AtomicReferenceArray b)在b)中創建一個新數組(而不是從地圖獲取舊數組),然後使用它爲特定Id更新地圖。 – CaptainHastings 2012-08-06 12:15:50