文章目錄
一、HashMap解析
二、Hashtable解析
三、Collections.synchronizedMap()解析
四、ConcurrentHashMap
六、ArrayList爲什麼是線程不安全的,Vector是線程安全的?
參考文獻
什麼叫做線程安全?
在一個線程中,某操作執行之後得到的是該操作想要的結果,而不是其他結果(被其他線程修改了)
一、HashMap解析
HashMap是線程不安全的,多線程情況下不推薦使用HashMap。它的key,value運行爲null
二、Hashtable解析
Hashtable在jdk1.1就有了,那麼它是怎樣實現線程安全的呢?主要看put、remove、get方法猜它肯定進行的同步控制的。於是看源碼:
//get它搞成了同步方法,保證了get的安全性
public synchronized V get(Object key) {
……
}
//synchronized,同樣
public synchronized V put(K key, V value) {
……
}
//也是搞成了同步方法
public synchronized V remove(Object key) {
……
}
所以爲什麼Hashtable是線程安全的,因爲它的remove,put,get做成了同步方法,保證了Hashtable的線程安全性。
每個操作數據的方法都進行同步控制之後,由此帶來的問題任何一個時刻只能有一個線程可以操縱Hashtable,所以其效率比較低。
三、Collections.synchronizedMap()解析
我們看源碼:
public int size() {
synchronized (mutex) {return m.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return m.isEmpty();}
}
public boolean containsKey(Object key) {
synchronized (mutex) {return m.containsKey(key);}
}
public boolean containsValue(Object value) {
synchronized (mutex) {return m.containsValue(value);}
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
public V put(K key, V value) {
synchronized (mutex) {return m.put(key, value);}
}
public V remove(Object key) {
synchronized (mutex) {return m.remove(key);}
}
public void putAll(Map<? extends K, ? extends V> map) {
synchronized (mutex) {m.putAll(map);}
}
public void clear() {
synchronized (mutex) {m.clear();}
}
我們驚人的發現,synchronizedMap只是將HashMap的操縱放在了同步代碼塊中來保證SynchronizedMap的線程安全性。因此,SynchronizedMap也可以允許key和value爲null。這樣帶來的問題也是任何一個時刻只能有一個線程可以操縱synchronizedMap,所以其效率比較低。
同樣,Collections下的SynchronizedXX也是用同樣方法實現線程安全性的。如SynchronizedSortedMap
四、ConcurrentHashMap
爲什麼ConcurrentHashMap可以多線程訪問呢?是因爲ConcurrentHashMap將Map分段了,每個段進行加鎖,而不是想Hashtable,SynchronizedMap是整個map加鎖,這樣就可以多線程訪問了。
如圖:
ConcurrentHashMap默認運行16個線程同時訪問該map。但是我們可以通過一個函數來設置增加或減少最大可運行訪問的線程數目。
//就是這個concurrencyLevel
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel)
所以就有了下面這幾個問題:
(1) 多線程可以同時寫一個ConcurrentHashMap的分段嗎?
不行。分段就像一個單獨的HashMap,只允許一個線程向其寫入數據
(2)多個線程可以同時寫入不同分段嗎?
這當然可以咯!
(3)多個線程可以同時從一個分段中讀數據嗎?
可以
(4)如果一個線程正在向一個分段寫入數據,其他線程可以從該分段中讀取數據嗎?
可以。但是讀取到最後更新的數據。
最後需要注意的一點是CoucrrentHashMap是不允許key和vlaue爲null的。
六、ArrayList爲什麼是線程不安全的,Vector是線程安全的?
Vector肯定是做了同步控制了的。看源碼
//同步方法
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
//同步方法
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
所以Vector也是用同步方法的方式來保證線程安全的。
---------------------
作者:我不是小白臉
來源:CSDN
原文:https://blog.csdn.net/wobushixiaobailian/article/details/84074885
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!