[英]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.