1.容器的概述:
ConcurrentMap集合類使用與底層原理分析
CopyOnWrite集合類使用與底層原理分析
并發與阻塞隊列Queue講解
模拟阻塞隊列實戰
ArrayBlockingQueue
ConcurrentLinkedQueue
SynchronousQueue
PriorityBlockingQueue優先級隊列
DelayQueue延遲隊列應用與實戰
2.同步類容器的問題
同步類容器的狀态都是串行化的。(100個請求,隻有一個請求執行,執行後釋放鎖其他請求才能執行)
ConcurrentModificationException并發修改導緻的目前線程更改異常
這些容器的同步功能其實都是有JDK的Collections.synchronized***等工廠方法去建立實作的。
同步類容器都是線程安全的,但在某些場景下可能需要加鎖來保護複合操作。
複合類操作如:疊代(反複通路元素,周遊完容器中所有的元素)、跳轉(根
據指定的順序找到目前元素的下一個元素)、以及條件運算。
這些複合操作在多線程并發地修改容器時,可能會表現出意外的行為,最經典
的便是ConcurrentModificationException,原因是當容器疊代的過程中,被
并發的修改了内容,這是由于早期疊代器設計的時候并沒有考慮并發修改的問題
3.同步類容器的使用
Vector、HashTable
同步類容器:
如Vector、HashTable。
這些容器的同步功能其實都是有JDK的Collections.synchronized***等
工廠方法去建立實作的。
其底層的機制無非就是用synchronized關鍵字對每個公用的方法都進行同
步,或者使用Object mutex對象鎖的機制使得每次隻能有一個線程通路容
器的狀态。
在一個同步類容器集合中,删除某個指定元素:m1();m2()方法會報異常ConcurrentModificationException。而m3()方法成功
package com.bfxy.thread.core.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
public class UseSyncCollection {
// 出現java.util.ConcurrentModificationException
public Collection<String> m1(Vector<String> list) {
for (String temp : list) {
if ("3".equals(temp)) {
list.remove(temp);
}
}
return list;
}
// 出現java.util.ConcurrentModificationException
public Collection<String> m2(Vector<String> list) {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String temp = iterator.next();
if ("3".equals(temp)) {
list.remove(temp);
}
}
return list;
}
//successful!
public Collection<String> m3(Vector<String> list) {
for (int i = 0; i < list.size(); i++) {
if ("3".equals(list.get(i))) {
list.remove(i);
}
}
return list;
}
public static void main(String[] args) {
Vector v = new Vector<>();
v.add("1");
v.add("2");
v.add("3");
UseSyncCollection test = new UseSyncCollection();
// Collection<String> ret1 = test.m1(v);
// System.err.println(ret1.toString());
// Collection<String> ret2 = test.m2(v);
// System.err.println(ret2.toString());
Collection<String> ret3 = test.m1(v);
System.err.println(ret3.toString());
// List<String> list = new ArrayList<>();
// Collections.synchronizedCollection(list);
}
}
Vector(同步)方法大多用synchronized修飾與List(非同步)都能夠使用方法3操作成功。
增強for循環以及遊标循環對集合容器的資料操作不是一個線程在操作,簡單for循環是單個線程操作
4.同步容器的實作:
1.其底層的機制無非就是用synchronized關鍵字對每個公用的方法都進行同步,
2.或者使用Object mutex對象鎖的機制使得每次隻能有一個線程通路容器的狀态。
ConcurrentModificationException并發修改導緻的目前線程更改異常
這些容器的同步功能其實都是有JDK的Collections.synchronized***等工廠方法去建立實作的。
// List<String> list = new ArrayList<>();
// Collections.synchronizedCollection(list);
這樣就把List變成同步容器了,實作線程安全了:方法中會建立
new SynchronizedCollection(list);
然後:SynchronizedCollection對象中有參數final Object mutex;(對象鎖)
duilist操作時候都是對對象鎖操作如:
public int size() {
synchronized (mutex) {return c.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}
public <T> T[] toArray(T[] a) {
synchronized (mutex) {return c.toArray(a);}
}
總結原理:會将list變成對象SynchronizedCollection;然後對list操作時候,會受到SynchronizedCollection對象中,mutex對象進行鎖處理