
Vector 是矢量隊列,它是 JDK1.0 版本添加的類。繼承于 AbstractList,實作了 List, RandomAccess, Cloneable 這些接口。 Vector 繼承了 AbstractList,實作了 List;是以,它是一個隊列,支援相關的添加、删除、修改、周遊等功能。 Vector 實作了 RandmoAccess 接口,即提供了随機通路功能。
JUC學習筆記(一)https://www.cnblogs.com/lm66/p/15118407.html JUC學習筆記(二)https://www.cnblogs.com/lm66/p/15118813.html JUC學習筆記(三)https://www.cnblogs.com/lm66/p/15118976.html
NotSafeDemo
異常内容
java.util.ConcurrentModificationException
問題: 為什麼會出現并發修改異常?
檢視 ArrayList 的 add 方法源碼
那麼我們如何去解決 List 類型的線程安全問題?
Vector 是矢量隊列,它是 JDK1.0 版本添加的類。繼承于 AbstractList,實作了 List, RandomAccess, Cloneable 這些接口。 Vector 繼承了 AbstractList,實作了 List;是以,它是一個隊列,支援相關的添加、删除、修改、周遊等功能。 Vector 實作了 RandmoAccess 接口,即提供了随機通路功能。RandmoAccess 是 java 中用來被 List 實作,為 List 提供快速通路功能的。在
Vector 中,我們即可以通過元素的序号快速擷取元素對象;這就是快速随機通路。 Vector 實作了 Cloneable 接口,即實作 clone()函數。它能被克隆。
和 ArrayList 不同,Vector 中的操作是線程安全的。
NotSafeDemo 代碼修改
現在沒有運作出現并發異常,為什麼?
檢視 Vector 的 add 方法
add 方法被 synchronized 同步修辭,線程安全!是以沒有并發異常
Collections 提供了方法 synchronizedList 保證 list 是同步線程安全的
沒有并發修改異常
檢視方法源碼
首先我們對 CopyOnWriteArrayList 進行學習,其特點如下:
它相當于線程安全的 ArrayList。和 ArrayList 一樣,它是個可變數組;但是和ArrayList 不同的時,它具有以下特性:
它最适合于具有以下特征的應用程式:List 大小通常保持很小,隻讀操作遠多于可變操作,需要在周遊期間防止線程間的沖突。
它是線程安全的。
因為通常需要複制整個基礎數組,是以可變操作(add()、set() 和 remove() 等等)的開銷很大。
疊代器支援 hasNext(), next()等不可變操作,但不支援可變 remove()等操作。
使用疊代器進行周遊的速度很快,并且不會與其他線程發生沖突。在構造疊代器時,疊代器依賴于不變的數組快照。
獨占鎖效率低:采用讀寫分離思想解決
寫線程擷取到鎖,其他寫線程阻塞
複制思想:
當我們往一個容器添加元素的時候,不直接往目前容器添加,而是先将目前容器進行 Copy,複制出一個新的容器,然後新的容器裡添加元素,添加完元素之後,再将原容器的引用指向新的容器。 這時候會抛出來一個新的問題,也就是資料不一緻的問題。如果寫線程還沒來得及寫會記憶體,其他的線程就會讀到了髒資料。
這就是 CopyOnWriteArrayList 的思想和原理。就是拷貝一份。
沒有線程安全問題
原因分析(重點):動态數組與線程安全
下面從“動态數組”和“線程安全”兩個方面進一步對CopyOnWriteArrayList 的原理進行說明。
“動态數組”機制
它内部有個“volatile 數組”(array)來保持資料。在“添加/修改/删除”資料時,都會建立一個數組,并将更新後的資料拷貝到建立的數組中,最後再将該數組指派給“volatile 數組”, 這就是它叫做 CopyOnWriteArrayList 的原因
由于它在“添加/修改/删除”資料時,都會建立數組,是以涉及到修改資料的操作,CopyOnWriteArrayList 效率很低;但是單單隻是進行周遊查找的話,效率比較高。
“線程安全”機制
通過 volatile 和互斥鎖來實作的。
通過“volatile 數組”來儲存資料的。一個線程讀取 volatile 數組時,總能看到其它線程對該 volatile 變量最後的寫入;就這樣,通過 volatile 提供了“讀取到的資料總是最新的”這個機制的保證。
通過互斥鎖來保護資料。在“添加/修改/删除”資料時,會先“擷取互斥鎖”,再修改完畢之後,先将資料更新到“volatile 數組”中,然後再“釋放互斥鎖”,就達到了保護資料的目的。
線程安全與線程不安全集合
集合類型中存線上程安全與線程不安全的兩種,常見例如:
ArrayList ----- Vector
HashMap -----HashTable
但是以上都是通過 synchronized 關鍵字實作,效率較低
Collections 建構的線程安全集合
ava.util.concurrent 并發包下
CopyOnWriteArrayList CopyOnWriteArraySet 類型,通過動态數組與線程安全個方面保證線程安全