![](/img/trans.png)
[英]Difference between Hashtable and Collections.synchronizedMap(HashMap)
[英]What happens when we pass hashtable inside Collections.synchronizedMap()
今天我在采訪中提出了一個問題。 問題是Collections.synchronizedMap()用於同步地圖,默認情況下不像hashmap那樣是線程安全的。 他的問題是,我們可以在這個方法中傳遞任何類型的地圖。 那么當我們在此方法中傳遞哈希表時會產生什么影響,因為哈希表默認是同步的。
映射的行為將是相同的,但性能將受到影響,因為每個方法將獲取兩個同步鎖而不是一個。
例如,考慮在結果映射上調用方法size()
。 Collections.SynchronizedMap
類中的實現如下所示:
public int size() {
synchronized(mutex) {return m.size();} // first lock
}
...其中, m.size()
調用Hashtable
的實現:
public synchronized int size() { // second lock
return count;
}
第一個鎖定對象是SynchronizedMap
的mutex
字段。 第二個鎖是隱式的 - Hashtable
實例本身。
您將有兩個同步級別:一個在同步映射本身級別,由互斥對象實現,另一個在包裝實例級別:
public boolean isEmpty() {
// first level synchronization
synchronized(mutex) {
// second level synchronization if c is a Hashtable
return c.isEmpty();
}
}
不需要額外的同步,可能導致性能降低。
另一個影響是,您將無法使用Hashtable
API,如Hashtable#elements
因為包裝的集合現在嚴格來說是一個Map
實例。
它將從java.util.Collections
包裝到SynchronizedMap
java.util.Collections
:
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<>(m);
}
synchronizedMap()
方法不區分傳遞給它的Map
的類型。
“他的問題是,但我們可以通過這種方法傳遞任何類型的地圖。”
答案是肯定的,因為SynchronizedMap
的構造函數接受其簽名中的每個Map
。
“那么當我們在此方法中傳遞哈希表時會產生什么影響,因為哈希表默認是同步的”
答案是:我們對ConcurrentHashMap
表示無知,這很可能是使用的工具而不是阻塞實現。
如果您在SynchronizedCollection
看到代碼。 這些方法會將調用委托給底層集合,但會在調用之上添加synchronized塊,就像這樣
public int size() {
synchronized (mutex) {return c.size();}
}
在HashTable
類中,大小的實現看起來像這樣
public synchronized int size() {
return count;
}
所以,如果你在通過HashTable
來SynchronizedCollection
,線程訪問到SynchronizedCollection
將不得不采取鎖在2級一次synchronized塊,另一個用於同步的方法。 如果有其他線程直接使用HashTable對象,即使線程在SynchronizedCollection
上獲得鎖定,它們也可以使用SynchronizedCollection
來阻塞線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.