HashMap(不是線程安全)與ConcurrentHashMap(線程安全)


HashMap不是線程安全的

ConcurrentHashMap是線程安全的

 

從JDK1.2起,就有了HashMap,正如前一篇文章所說,HashMap不是線程安全的,因此多線程操作時需要格外小心。

在JDK1.5中,偉大的Doug Lea給我們帶來了concurrent包,從此Map也有安全的了。

 

 

ConcurrentHashMap具體是怎么實現線程安全的呢,肯定不可能是每個方法加synchronized,那樣就變成了HashTable。

從ConcurrentHashMap代碼中可以看出,它引入了一個“分段鎖”的概念,具體可以理解為把一個大的Map拆分成N個小的HashTable,根據key.hashCode()來決定把key放到哪個HashTable中。

在ConcurrentHashMap中,就是把Map分成了N個Segment,put和get的時候,都是現根據key.hashCode()算出放到哪個Segment中:

 

 

 

 

 

測試程序:

import java.util.concurrent.ConcurrentHashMap;
 
public class ConcurrentHashMapTest {
    
    private static ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<Integer, Integer>();
    public static void main(String[] args) {
        new Thread("Thread1"){
            @Override
            public void run() {
                map.put(3, 33);
            }
        };
        
        new Thread("Thread2"){
            @Override
            public void run() {
                map.put(4, 44);
            }
        };
        
        new Thread("Thread3"){
            @Override
            public void run() {
                map.put(7, 77);
            }
        };
        System.out.println(map);
    }
}

 

ConcurrentHashMap中默認是把segments初始化為長度為16的數組。
根據ConcurrentHashMap.segmentFor的算法,3、4對應的Segment都是segments[1],7對應的Segment是segments[12]。

(1)Thread1和Thread2先后進入Segment.put方法時,Thread1會首先獲取到鎖,可以進入,而Thread2則會阻塞在鎖上:

 

 

(2)切換到Thread3,也走到Segment.put方法,因為7所存儲的Segment和3、4不同,因此,不會阻塞在lock():

 

 

 

以上就是ConcurrentHashMap的工作機制,通過把整個Map分為N個Segment(類似HashTable),可以提供相同的線程安全,但是效率提升N倍,默認提升16倍。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM