摘要:機(jī)制已經(jīng)相關(guān)類和我們知道是用于替代的,是線程安全的容器。如果使用迭代器來做上面的操作,會(huì)拋出異常。實(shí)現(xiàn)原理是線程安全容器相對于,底層通過復(fù)制數(shù)組的方式來實(shí)現(xiàn)。線程在線程迭代的間隙中將部分的數(shù)據(jù)修改了已經(jīng)調(diào)用了。
COW機(jī)制已經(jīng)相關(guān)類
Vector和SynchronizedList
我們知道ArrayList是用于替代Vector的,Vector是線程安全的容器。因?yàn)樗鼛缀踉诿總€(gè)方法聲明處都加了synchronized關(guān)鍵字來使容器安全。
如果使用Collections.synchronizedList(new ArrayList())來使ArrayList變成是線程安全的話,也是幾乎都是每個(gè)方法都加上synchronized關(guān)鍵字的,只不過它不是加在方法的聲明處,而是方法的內(nèi)部。
多線程下for循環(huán)迭代Vector或者SynchronizedList,進(jìn)行delete和get操作會(huì)發(fā)生數(shù)組下標(biāo)錯(cuò)誤的異常。
在JDK5以后,Java推薦使用for-each(迭代器)來遍歷我們的集合,好處就是簡潔、數(shù)組索引的邊界值只計(jì)算一次。
如果使用for-each(迭代器)來做上面的操作,會(huì)拋出ConcurrentModificationException異常。
如果想要完美解決上面所講的問題,我們可以在遍歷前加鎖:
遍歷一下容器都要我加上鎖,這這這不是要慢死了嗎。的確是挺慢的。因?yàn)榧渔i粒度太大。
CopyOnWriteArrayList是同步List的替代品,CopyOnWriteArraySet是同步Set的替代品。
Hashtable、Vector加鎖的粒度大(直接在方法聲明處使用synchronized)
ConcurrentHashMap、CopyOnWriteArrayList加鎖粒度小(用各種的方式來實(shí)現(xiàn)線程安全,比如我們知道的ConcurrentHashMap用了cas鎖、volatile等方式來實(shí)現(xiàn)線程安全..)
JUC下的線程安全容器在遍歷的時(shí)候不會(huì)拋出ConcurrentModificationException異常
所以一般來說,我們都會(huì)使用JUC包下給我們提供的線程安全容器,而不是使用老一代的線程安全容器。
CopyOnWriteArrayList實(shí)現(xiàn)原理
CopyOnWriteArrayList是線程安全容器(相對于ArrayList),底層通過復(fù)制數(shù)組的方式來實(shí)現(xiàn)。
CopyOnWriteArrayList在遍歷的使用不會(huì)拋出ConcurrentModificationException異常,并且遍歷的時(shí)候就不用額外加鎖
元素可以為null
/** 可重入鎖對象 */ final transient ReentrantLock lock = new ReentrantLock(); /** CopyOnWriteArrayList底層由數(shù)組實(shí)現(xiàn),volatile修飾 */ private transient volatile Object[] array; final Object[] getArray() { return array; } final void setArray(Object[] a) { array = a; } // 初始化CopyOnWriteArrayList相當(dāng)于初始化數(shù)組 public CopyOnWriteArrayList() { setArray(new Object[0]); }
CopyOnWriteArrayList底層就是數(shù)組,加鎖就交由ReentrantLock來完成。
通過代碼我們可以知道:在add(),set(),remove() 的時(shí)候就上鎖,并復(fù)制一個(gè)新數(shù)組,增加操作在新數(shù)組上完成,將array指向到新數(shù)組中,最后解鎖。
在修改時(shí),復(fù)制出一個(gè)新數(shù)組,修改的操作在新數(shù)組中完成,最后將新數(shù)組交由array變量指向。
寫加鎖,讀不加鎖
CopyOnWriteArrayList缺點(diǎn)
內(nèi)存占用:如果CopyOnWriteArrayList經(jīng)常要增刪改里面的數(shù)據(jù),經(jīng)常要執(zhí)行add()、set()、remove()的話,那是比較耗費(fèi)內(nèi)存的。
因?yàn)槲覀冎烂看?b>add()、set()、remove()這些增刪改操作都要復(fù)制一個(gè)數(shù)組出來。
數(shù)據(jù)一致性:CopyOnWrite容器只能保證數(shù)據(jù)的最終一致性,不能保證數(shù)據(jù)的實(shí)時(shí)一致性。
從上面的例子也可以看出來,比如線程A在迭代CopyOnWriteArrayList容器的數(shù)據(jù)。線程B在線程A迭代的間隙中將CopyOnWriteArrayList部分的數(shù)據(jù)修改了(已經(jīng)調(diào)用setArray()了)。但是線程A迭代出來的是原有的數(shù)據(jù)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/73516.html
摘要:體現(xiàn)的就是適配器模式。數(shù)組對象集合世界中的機(jī)制機(jī)制集合世界中比較常見的錯(cuò)誤檢測機(jī)制,防止在對集合進(jìn)行遍歷過程當(dāng)中,出現(xiàn)意料之外的修改,會(huì)通過異常暴力的反應(yīng)出來。而在增強(qiáng)循環(huán)中,集合遍歷是通過進(jìn)行的。 前言 學(xué)習(xí)情況記錄 時(shí)間:week 2 SMART子目標(biāo) :Java 容器 記錄在學(xué)習(xí)Java容器 知識(shí)點(diǎn)中,關(guān)于List的重點(diǎn)知識(shí)點(diǎn)。 知識(shí)點(diǎn)概覽: 容器中的設(shè)計(jì)模式 從Array...
摘要:用于創(chuàng)建子進(jìn)程等同于當(dāng)前進(jìn)程的副本。這個(gè)函數(shù)會(huì)有兩次返回,將子進(jìn)程的返回給父進(jìn)程,返回給子進(jìn)程。當(dāng)父子進(jìn)程中有更改相應(yīng)段的行為發(fā)生時(shí),再為子進(jìn)程相應(yīng)的段分配物理空間。中斷例程中,就會(huì)把觸發(fā)的異常的頁復(fù)制一份,于是父子進(jìn)程各自持有獨(dú)立的一份。 前言 只有光頭才能變強(qiáng) 在讀《Redis設(shè)計(jì)與實(shí)現(xiàn)》關(guān)于哈希表擴(kuò)容的時(shí)候,發(fā)現(xiàn)這么一段話: 執(zhí)行BGSAVE命令或者BGREWRITEAOF命令的...
摘要:可以看到,該結(jié)構(gòu)體存儲(chǔ)了關(guān)于變量值,有幾個(gè)變量指向該結(jié)構(gòu)體,變量類型,是否為引用變量等信息。這個(gè)就是寫時(shí)復(fù)制,在作怪,他沒有在賦值的時(shí)候就分裂成兩個(gè)結(jié)構(gòu)體,而是在我們改寫其中一個(gè)變量時(shí)發(fā)生效果,屬于一種慢復(fù)制也稱慢分裂。 想要走到技術(shù)的天花板,那么學(xué)習(xí)過程中在于知其然且知其所以然。 今天我們來討論一下PHP底層的寫時(shí)復(fù)制(也稱寫時(shí)分裂)。 首先我們先來看看一段代碼:showImg(ht...
摘要:問題農(nóng)場一頭小母牛,母牛每年生母牛。母牛歲產(chǎn)母牛,年后多少牛前提第一頭母牛已經(jīng)歲思路脈絡(luò)面向?qū)ο蠡舅枷耄⒁鉅顟B(tài)和行為,抽象出對應(yīng)的屬性和方法思想考慮類母牛農(nóng)場一開始可能不會(huì)想到把農(nóng)場設(shè)計(jì)為一個(gè)類。 問題: 農(nóng)場一頭小母牛, 母牛每年生母牛。 母牛5歲產(chǎn)母牛, 20年后多少牛? PS:前提:第一頭母牛已經(jīng)>=5歲 思路脈絡(luò): 面向?qū)ο蠡舅枷耄⒁鉅顟B(tài)和行為,抽象出對...
摘要:快速了解繼承在的繼承關(guān)系里子類可以從獲取父類的所有的公共和受保護(hù)成員字段方法和內(nèi)部類。阻止繼承有些情況下,我們可能不希望子類覆蓋父類的方法,這時(shí)候,用關(guān)鍵字修飾方法即可實(shí)現(xiàn)該目的。 和現(xiàn)實(shí)世界中:子女可以繼承父母的一些特征(如:基因)、財(cái)產(chǎn)等一樣。OOP 中也有提供類似的特性,一個(gè)類完全可以從其它類里獲得一些屬性和方法,而不需要我們自己重新定義。這種特性簡單但強(qiáng)大 (Simple an...
閱讀 1684·2023-04-25 20:16
閱讀 3838·2021-10-09 09:54
閱讀 2696·2021-09-04 16:40
閱讀 2517·2019-08-30 15:55
閱讀 830·2019-08-29 12:37
閱讀 2733·2019-08-26 13:55
閱讀 2903·2019-08-26 11:42
閱讀 3144·2019-08-23 18:26