簡體   English   中英

當我們在Collections.synchronizedMap()中傳遞哈希表時會發生什么

[英]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;
}

第一個鎖定對象是SynchronizedMapmutex字段。 第二個鎖是隱式的 - 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;
}

所以,如果你在通過HashTableSynchronizedCollection ,線程訪問到SynchronizedCollection將不得不采取鎖在2級一次synchronized塊,另一個用於同步的方法。 如果有其他線程直接使用HashTable對象,即使線程在SynchronizedCollection上獲得鎖定,它們也可以使用SynchronizedCollection來阻塞線程。

暫無
暫無

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

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