2017-06-17 87 views
-2

我有一個CHM併發的HashMap中的線程安全的方式行爲不

private ConcurrentHashMap<Integer,Integer>pR = new ConcurrentHashMap<>(); 

我有一個增加它的價值

public void incrementPR(int count){ 

     Integer value = this.pR.get(count); 
     if(value == null){ 
      this.pR.put(count,1); 
     } else { 
      this.pR.put(count,value+1); 
     } 
    } 

這種方法是從一個端點使用JMeter的,要是我解僱500稱爲方法併發請求hashmap的其值不是500而是437,430等它不表現線程安全的方式,我們如何獲得同樣的安全性

+0

ConcurrentHashMap不保證原子操作的序列。 – user2357112

+0

這樣才能使hashmap線程安全同步是唯一的方法? – Rahul

回答

1

你打破「get c urrent價值「和」增加它「和」保存回地圖「在一些語句。現在,當這些語句同時運行時,你會得到有線結果。您的失敗與併發映射無關。你應該爲你的代碼使用一些併發控制機制(比如信號量,鎖定等)。欲瞭解更多信息,請參考這個問題: Java Concurrency Incrementing a Value

如果您有興趣有效的解決方案(不使用鎖定機制)對你的意圖,你可以使用AtomicInteger

AtomicInteger atomicInteger = new AtomicInteger(); 
//when you want to add your number, use this code 
atomicInteger.getAndAdd(1); 

但是,如果你有這個沉重的負擔語句,使用AtomicLong可能是一個瓶頸(因爲它使用比較和交換cpu指令)。在這種情況下,最好使用LongAdder爲:

LongAdder longAdder = new LongAdder(); 
//when you want to add your number, use this code 
longAdder.increment() 
+0

你說的是同步的權利?是否還有其他更好的方法 – Rahul

+0

我如何在我的地圖中實現這個需要一個整數作爲輸入的地圖? – Rahul

+0

當您需要增加您的值時,只需將map聲明爲Map '現在使用'map.get(myKey).increment()'。 –

0

當一個類被描述爲「線程安全」的評價通常是是類將確保併發呼叫之間有足夠的排斥它的方法來維持類完整性(和相關的不變量)。

它並不意味着它將確保另一個類不能在調用之間修改它。

在你的情況下,如果一個線程調用this.pR.get(count);,然後在調用put之前另一個線程調用它,它們正在競爭哪個將更新該對象,並且它顯示「丟失」計數。

您需要對incrementPR調用進行一些同步。

在這種情況下,容易和明顯的答案是:

public synchronized void incrementPR(int count){ 
    //.... 
} 

事實上與同步有可能沒有必要使用同步映射。從所提供的片段中不清楚。

+0

燁我用同步,它工作得很好,我希望能爲一些更好的方法,因爲我覺得,同步導致的性能影響,雖然不是很明顯,當其他變量都包括在這是更好的鎖或同步於該模型 – Rahul

+0

將refect案件 ? – Rahul

+0

@Rahul我提供了最簡單的答案,但實際上我會推薦一個鎖。我相信'synchronized'在Java中是一個糟糕的設計,你應該明確聲明和使用'Lock'對象。爲每個對象提供一個監視器和方法膨脹(以及可能的性能膨脹),這樣做是非常不必要的。在一個好的實現中,你應該能夠達到相同的性能,除非你需要嘗試鎖類型,在這種情況下'synchronized'失敗很快。 – Persixty