CopyOnWriteArrayList原始碼解讀

2021-06-18 00:05:10 字數 3759 閱讀 7388

概述copyonwritearraylist是jdk concurrent包中提供的乙個非阻塞型的,執行緒安全的list實現。

copyonwritearraylist在進行資料修改時,都不會對資料進行鎖定,每次修改時,先拷貝整個陣列,然後修改其中的一些元素,完成上述操作後,替換整個陣列的指標。

對copyonwritearraylist進行讀取時,也不進行資料鎖定,直接返回需要查詢的資料,如果需要返回整個陣列,那麼會將整個陣列拷貝乙份,再返回,保證內部array在任何情況下都是唯讀的。

應用場景

正因為上述讀寫特性,如果需要頻繁對copyonwritearraylist進行修改,而很少讀取的話,那麼會嚴重降低系統效能。

因為沒有鎖的干預,所以copyonwritearraylist在少量修改,頻繁讀取的場景下,有很好的併發效能。

資料結構

copyonwritearraylist中,包含乙個array陣列物件,這個物件,只能由getarray()和setarray()兩個方法訪問,原始碼如下:

private

volatile

transient

object

array

;final

object

getarray

()final

void

setarray

(object

a)

併發安全保證

copyonwritearraylist在併發情況下,可以提供高效能的併發讀取,並且保證讀取的內容一定是正確的,不受多執行緒併發問題影響的。在本文中,我們從建構函式的併發安全性、訪問單個元素的併發安全性、訪問整個陣列的併發安全性和寫操作的併發安全性,四個方面進行分析。

建構函式的併發安全性

copyonwritearraylist提供了三個建構函式,分別為

上述三個方法的原始碼如下:

public

copyonwritearraylist

()/**

* 根據傳入引數c的長度,構造乙個同樣長度的object物件,並且將c的內容,依次填入此object物件中

* 注意:

* 1. 這裡對於c中內容的複製,是淺拷貝而非深拷貝

* 2. 這裡的建構函式,未顯式判斷c是否為null,實際上如果c為null,會丟擲空指標異常

*/public

copyonwritearraylist

(collection

<?

extends

e>c)

/*** 根據傳入引數的長度,構造出乙個同樣長度,內容一致的陣列物件,封裝在copyonwritearraylist中

* 注意:

* 1. 這裡對於陣列內容的複製,是淺拷貝而非深拷貝

* 2.

這裡的建構函式,未顯式判斷傳入引數是否為null,實際上如果傳入引數為null,會丟擲空指標異常

*/public

copyonwritearraylist(e

tocopyin

)

訪問單個元素的併發安全性

訪問單個元素時,不會對原有陣列造成任何影響,所以肯定是執行緒安全的。這裡列舉一兩個方法的實現原始碼,其他的不再贅述:

public

e get

(int

index

)public

intindexof

(objecto)

private

static

intindexof

(objecto,

object

elements

,int

index

,int

fence

)else

return-1

;}

訪問整個陣列的併發安全性

訪問整個陣列的操作,包括clone以及toarray方法,這些方法在執行時,不會直接返回內部封裝的array物件引用,而是將其拷貝乙份,再返回。注意,這裡的拷貝,也是淺拷貝。

原始碼如下:

www.520xunlong.com

public

object

toarray

()public

<

t>t

toarray

(t a)}

public

object

clone

()catch

(clonenotsupportedexceptione)

}

寫操作的併發安全性

寫操作的併發安全性,是copyonwritearraylist中最重要的一點,只***寫操作是安全的,才能保證併發是安全的。

set方法,是寫操作的乙個基本方法,其原始碼如下:

public

e set

(int

index

,e element

)else

return(e

)oldvalue;}

finally

}

為list末尾新增乙個新元素,使用add方法,其原始碼如下:

public

boolean

add(

e e)

finally

}

同時,也可以將某個元素加入到某個特定的位置,如下所示:

public

void

add(

intindex

,e element

)else

newelements

[index]=

element

;setarray

(newelements);}

finally

}

copyonwritearraylist同時也提供了從list中,移除某個元素的方法,原始碼如下:

public

e remove

(int

index

)else

return(e

)oldvalue;}

finally

}

也可以直接移除list中的某個物件,原始碼如下:

public

boolean

remove

(objecto)

setarray

(newelements

);return

true

;/* 找到了需要刪除的元素,並正常刪除,返回true */

}else

}/* 當需要移除的元素,在陣列最後,直接將新的陣列賦值過去 */if(

eq(o,

elements

[newlen

]))}

/* 未找到需要刪除的元素,返回false */

return

false;}

finally

}

其他修改的方法,原理上都是類似的,這裡不再贅述。ss

azkaban web server原始碼解析

azkaban主要用於hadoop相關job任務的排程,但也可以應用任何需要排程管理的任務,可以完全代替crontab。azkaban主要分為web server 任務上傳,管理,排程 executor server 接受web server的排程指令,進行任務執行 1.資料表 projects 工...

JDK LinkedHashMap原始碼解析

今天來分析一下jdk linkedhashmap的源 public class linkedhashmapextends hashmapimplements map可以看到,linkedhashmap繼承自hashmap,並且也實現了map介面,所以linkedhashmap沿用了hashmap的大...

Redux原始碼createStore解讀常用方法

const store createstore reducer,preloadedstate enhancer 直接返回當前currentstate,獲取state值,return state 我覺得應該深轉殖乙個新的物件返回,不然有可能會被外部修改 function getstate consol...