Java併發(三)ConcurrentHashMap鎖分段機制
阿新 • • 發佈:2019-02-11
- Java 5.0 在 java.util.concurrent 包中提供了多種併發容器類來改進同步容器
的效能。 - ConcurrentHashMap 同步容器類是Java 5 增加的一個執行緒安全的雜湊表。對
與多執行緒的操作,介於 HashMap 與 Hashtable 之間。內部採用“鎖分段”
機制替代 Hashtable 的獨佔鎖。進而提高效能。 - 此包還提供了設計用於多執行緒上下文中的 Collection 實現:
ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、
CopyOnWriteArrayList 和 CopyOnWriteArraySet。當期望許多執行緒訪問一個給
定 collection 時,ConcurrentHashMap 通常優於同步的 HashMap,
ConcurrentSkipListMap 通常優於同步的 TreeMap。當期望的讀數和遍歷遠遠
大於列表的更新數時,CopyOnWriteArrayList 優於同步的 ArrayList。
例子:
在一個方法中對一個List讀的同時又往裡面寫操作,會產生錯誤
class MyThread implements Runnable{
private static List<String>list = new ArrayList<String>();
static{
list.add("AA");
list.add("BB");
list.add("CC");
}
@Override
public void run() {
Iterator<String> it = list.iterator();
// 每次讀值的同時又寫值
while(it.hasNext()){
System.out.println(it.next());//讀值
list.add("AA");//寫值
}
}
}
測試:
public static void main(String[] args) {
MyThread mt = new MyThread();
for(int i=0;i<10;i++){
new Thread(mt).start();
}
System.out.println(Thread.currentThread()+"執行完畢" );
}
輸出:
AA
AA
AA
Thread[main,5,main]執行完畢
AA
AA
AA
AA
Exception in thread "Thread-5" Exception in thread "Thread-7" Exception in thread "Thread-6" Exception in thread "Thread-0" AA
AA
AA
我們發現main執行緒的執行雖然列印了語句,但是程式確保錯了
Exception in thread "Thread-5" Exception in thread "Thread-7" Exception in thread "Thread-6" Exception in thread "Thread-0" AA
這是因為在原生的list並未對執行緒安全問題進行優化
CopyOnWriteArrayList/CopyOnWriteArraySet
class MyThread implements Runnable{
private static CopyOnWriteArrayList<String>list = new CopyOnWriteArrayList<String>();
static{
list.add("AA");
list.add("BB");
list.add("CC");
}
@Override
public void run() {
Iterator<String> it = list.iterator();
// 每次讀值的同時又寫值
while(it.hasNext()){
System.out.println(it.next());//讀值
list.add("AA");//寫值
}
}
}
主函式不變,測試輸出:
正常執行,沒有報錯
總結:
- 直接使用傳統的list執行的時候會報錯
- 使用 CopyOnWriteArrayList、CopyOnWriteArraySet:寫入複製,
- 每次寫入時底層會複製一個list或set
- 雖然使得讀寫可以同時進行不報錯但是效率不高