簡體   English   中英

鏈接線程安全集合是否是線程安全的?

[英]Are chained thread safe collections thread safe?

如果我有以下聲明:

Map<String, Map<String, Person>> families = 
   Collections.synchronizedMap(new HashMap<String, Map<String, Person>>());

如果我再這樣打一個電話:

families.get(lastName).put(firstName, new Person());

這個線程安全嗎? 對我來說,似乎只有兩個地圖之一是同步的,但是如果不通過外部同步地圖就無法進入內部地圖,所以我不確定...

到目前為止,在兩個答案中都提出了出色的建議,謝謝大家! 但是現在我在想如果我這樣做:

families.put(lastName, Collections.synchronizedMap(new HashMap<String, Person>());

然后我的鏈式呼叫了嗎,整個鏈條線程安全嗎? get(lastName)put(firstName, new Person())之間是否可能另一個線程可以獲取內部映射? 我在想,如果我希望整個鏈線程安全,則需要將其放在同步塊中,但我也想知道這是否也可以工作...

您將通過同步的外部映射獲取內部映射,但是隨后您可以使用它來做您想做的事情。 因此,這不是線程安全的。

如果您確實希望在這種情況下實現線程安全,那么我將創建一個包含地圖映射的對象,然后您可以通過同步訪問器來控制訪問。 我建議在大多數情況下(這是您組成集合的集合)的最佳做法。

內部映射不是線程安全的。

如果還有其他線程

families.get(lastName).put(firstName, new Person());

使用相同的 lastName ,則有可能一個線程獲取內部映射,然后另一個線程獲取內部映射,然后兩個線程同時調用put並破壞所有內容。

僅使用synchronizedMap不足以實現正確的並發,通常,您需要顯式地鎖定每個事務 ,而不是每個方法調用

完全有可能在調用外部get()和內部put()之間,其他一些線程也調用外部get()並獲取相同的內部映射。 但是由於它是同步的,所以無論如何應該是安全的。

問題是當您在外部地圖中放置一些東西時。 線程如何確定是否有必要創建新的內部映射? 假設您有如下代碼:

if (!families.containsKey(lastName)) {
  families.put(lastName, Collections.synchronizedMap(new HashMap<String, Person>());
}

現在,這絕對是不安全的,因為其他一些線程可能同時執行相同的操作,因此您最終創建了兩個內部映射,其中一個內部映射立即成為垃圾收集的候選對象。

只同步適用於整個結構的所有方法,而不使用同步映射會更好。 它也可能會更快,因為您只需要一個同步級別。

暫無
暫無

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

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