2017-07-18 13 views
-1

我們需要同步這裏private static Map對象如果多個線程使用getObject方法,先用給定的密鑰檢查上map值,如果沒有找到,然後把新的對象使用該密鑰對map對象。如果多個線程使用公共方法讀取特定鍵的值,我們是否需要在一個私有靜態Map對象上進行同步?

private static Map<String, Object> map = new HashMap<>(); 

public Object getObject(String key){ 
    Object obj = map.get(key); 
    if(obj == null){ 
     obj = new Object(); 
     map.put(key, obj); 
    } 
    return obj; 
} 

回答

1

你不做只讀。 您也將值放入地圖中,並且HashMap不適用於併發線程(如果其中至少有一個線程在地圖上進行了某些操作)。

所有這一切都應該是同步的,以避免線程之間的競爭條件:

Object obj = map.get(key); 
if(obj == null){ 
    obj = new Object(); 
    map.put(key, obj); 
} 

的競爭條件實施例:

對於沒有包含在映射中的鍵"a",一個線程可能被暫停在這裏:

if(obj == null){ 

另一個線程可以用鑰匙"a"執行代碼等都提出ŧ他在地圖中的元素,因爲它還沒有被包含。
當第一個線程恢復時,它將覆蓋密鑰"a"的地圖內容。

請注意,如果您使用ConcurrentHashMap,則可以使用putIfAbsent()確保以原子方式執行操作(檢查並放置,如果不退出)。

+0

感謝您的回答,我有一個關於putIfAbsent()的問題,在這裏我們需要傳遞一個新創建的對象,這是不好的,我想創建對象只有當它在地圖中丟失。 –

+1

'map.computeIfAbsent(key,k - > new Object())'。 –

+0

謝謝這會幫助我。 –

2

它說,它right there in the Javadoc

請注意,此實現不是同步的。如果多個線程同時訪問哈希映射,並且至少有一個線程在結構上修改了映射,則它必須在外部同步。 (結構上的修改是指添加或刪除一個或多個映射的操作;僅改變與該一個實例已經包含一個鍵相關聯的值不被結構上的修改。)

你打電話put如果該值是空(或不存在),所以你正在進行結構修改。如果您從多個線程調用此方法,則需要同步。

相關問題