Java 集合框架中,ArrayList、LinkedList、HashMap 等主流容器均為非線程安全。早期 Java 提供了同步容器解決並發問題,但隨著並發需求增長,其性能瓶頸與安全隱患逐漸暴露,催生了 JUC 並發包的誕生。
| 容器 | 對應非線程安全版本 | 實現機制 |
|---|---|---|
| Vector | ArrayList | 所有方法 synchronized |
| Stack | Vector 子類 | 繼承 Vector 同步特性 |
| Hashtable | HashMap | 所有方法 synchronized |
List<String> syncList = Collections.synchronizedList(new ArrayList<>()); Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>()); Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
本質:通過裝飾器模式,用互斥鎖包裝每個方法調用。
單個方法雖然同步,但「檢查-然後執行」等複合操作仍不安全:
// 線程不安全示例:遍歷時刪除
for (int i = 0; i < vector.size(); i++) {
vector.remove(i); // size() 與 remove() 非原子,拋 ConcurrentModificationException
}
解決方案:客戶端加鎖(擴展同步塊)
synchronized (vector) {
for (int i = 0; i < vector.size(); i++) {
vector.remove(i);
}
}
ArrayList 迭代器通過 modCount 檢測並發修改:
expectedModCount:創建迭代器時記錄的修改計數modCount:每次 add/remove 遞增ConcurrentModificationException核心思想:寫時復制,讀操作無鎖,寫操作復制新數組
| 優點 | 缺點 |
|---|---|
| 讀性能極佳,適合讀多寫少 | 內存佔用大(雙份數組) |
| 迭代器不拋 ConcurrentModificationException | 只能保證最終一致性,非實時 |