2013-10-07 58 views
5

我讀過哈希表是線程安全的,因爲它是同步的。考慮這段代碼片段哈希表中的哈希表和同步

if(!hashtable.contains(key)){ 
hashtable.put(key,value); 
} 

散列表上的操作可能不同步。例如,如果Thread t1訪問hastable並檢查密鑰,並且同時Thread t2檢查密鑰,則在t1執行put之前。現在兩個線程位於if塊的內部並且發生鍵值覆蓋。

所以同步塊是必要的。

synchronized { 
if(!hashtable.contains(key)){ 
    hashtable.put(key,value); 
    } 
} 

這種理解是否正確?或者對可操作的操作安全可靠。當我讀到這個時,我有這個疑問post on race condition

+0

是的,這是正確的。 – SJuan76

回答

9

你是對的,你需要​​塊。 Hashtable's方法爲​​,但在調用​​塊之外的多種方法時仍有可能進行競賽。例如,當兩個線程同時調用put時,內置同步可以防止出現問題。

您可能還需要尋找到ConcurrentHashMap

3

Hashtable方法是同步的,但只針對特定種族的條件提供了方法級別的保護。 (所以Hashtable —不像HashMap —如果多個線程同時嘗試修改數據將不會內部損壞)。只有在這個意義上,Hashtable是線程安全的。

無論Hashtable也不是ConcurrentHashMap將提供更高級別的同步,這通常是*你需要什麼,當你正在執行多步操作。無論如何,你需要一個外部的​​阻止,所以你不妨使用較低開銷HashMap而不是Hashtable

  *正如傑夫·斯托裏指出的,ConcurrentHashMap有一個putIfAbsent方法已經做了你在你的代碼正在做什麼。對於其他多步驟操作,ConcurrentHashMap可能有也可能沒有一種方法可以自動執行所需的操作。

+1

'ConcurrentHashMap'有一個'putIfAbsent'方法,它將自動檢查是否包含密鑰,如果不存在則將其放入。 –

+0

@JeffStorey - 是的,忘記了這一點。謝謝。我會相應地更新我的答案。但是,對於其他多步驟操作,可能需要外部同步。 –