併發容器(2)

2021-10-07 17:22:52 字數 3665 閱讀 6377

同步容器通過synchronized關鍵字修飾容器,保證同一時間內只有乙個執行緒在使用容器,從而使得容器執行緒安全。

允許多執行緒同時使用容器,並且保證執行緒安全。核心:鎖,cas,cow,分段鎖。

vector:

stack: stack實現的是先進後出的棧,入棧出棧都使用synchronized

hashtable:

實現map介面,實現的功能和hashmap基本一致(hashtable 不可出現null,hashmap鍵值可以使用null);

hashtable在使用的時候也用synchronized修飾了方法

arraylist、hashmap 不是執行緒安全的。

collections提供了同步集合類

list list = collections.

synchronizedlist

(new

arraylist()

);set set = collections.

synchronizedset

(new

hashset()

);

copyonwritearraylist:寫的時候複製容器,新增元素的時候,先複製乙個新的容器。讀寫分離。

讀: 從原來的容器讀

寫:把資料寫入到新的容器。

寫資料過程:

public

boolean

add(e e)

finally

}

缺點

1.記憶體占有問題。

2.資料一致性問題:只能保證資料的最終一致性,不能保證資料的實時一致性。

hashmap:是執行緒不安全的,在併發情況下會產生死鎖。

hashtable:執行緒安全,代價大,簡單粗暴,get/put所有的操作都是synchronized修飾。相當於給整個hashtable加了一把大鎖。

concurrenthashmap: 可以支援併發的讀寫,支援高併發的檢索和更新。

在jdk1.7: 陣列+鍊錶+分段鎖

在jdk1.8: 陣列+鍊錶+紅黑樹

不能使用null作為key或者value

取消segments,採用hashentry儲存資料

1.當乙個位置有多個元素的時候,concurrenthashmap優先採用鍊錶的形式儲存

2.當鍊表的元素個數大於8個,並且陣列的長度小於64時,進行擴容。

3.當鍊表的元素個數大於8個,並且陣列長度大於64時,鍊錶轉為紅黑樹。

原理:

1.第一次新增元素:

初始長度:16
—>用hash演算法算出元素存放在陣列的哪個位置

—>如果出現放在同乙個位置的時候,優先採用鍊錶的形式存放

—>在同乙個位置的個數達到8個以上的時候,如果陣列的長度小於64的時候,擴容陣列。

—>陣列的長度大於等於64,會將該節點的鍊錶轉換為紅黑樹。

put:

如果沒有初始化table先呼叫inittable()方法進行初始化過程

如果沒有hash衝突就直接cas插入。

如果陣列在擴容操作就先進行擴容。

如果存在hash衝突,就加鎖來保證執行緒安全(一種是鍊錶形式,直接遍歷到尾端插入,一種是紅黑樹就按照紅黑樹的結構插入)

最後乙個如果鍊錶的數量大於8,就要先轉換成紅黑樹的結構

如果新增成功,就呼叫addcount()方法統計size,並且檢查是否要擴容

**:

final v putval

(k key, v value,

boolean onlyifabsent)

elseif(

(fh = f.hash)

== moved)

tab =

helptransfer

(tab, f)

;else

node

pred = e;if(

(e = e.next)

== null)}}

else

if(f instanceof

treebin)}

}}if(bincount !=0)

}}addcount

(1l, bincount)

;return null;

}

單項佇列:只能向隊尾新增元素,從對頭刪除元素。

雙向佇列:頭和尾都支援元素的入隊和出隊。

放入資料:

add(object)

offer(object): 如果佇列可以容納,則返回true,否則返回false,該方法不阻塞當前執行方法的執行緒。

put(e): 把object加入到blockingqueue,如果佇列沒有空間,則呼叫此方法的執行緒被阻塞直到佇列有空間在繼續。

獲取資料:

poll(time); 取走佇列排在首位的元素,如果不能立即取走,則可以等設定的time引數的時間,取不到返回false;

poll(timeout):

take(object):取走隊首的元素,如果隊列為空,當前執行緒阻塞,直到佇列中有新的元素加入。

實現類

linkedblockingqueue

final object[

] items;

arrayblockingqueue

delayqueue: 元素只能當其指定的延遲時間到了,才能從佇列中獲取該元素,

priorityblockingqueue: 基於優先順序的阻塞佇列。

synchronousqueue: 無緩衝的等待佇列。(只有乙個元素)

arrayblockqueue

/** main lock guarding all access */

final reentrantlock lock;

/** condition for waiting takes */

private

final condition notempty;

/** condition for waiting puts */

private

final condition notfull;

新增元素:

public

void

put(e e)

throws interruptedexception

finally

}

併發基礎 11 併發 容器

要實現乙個執行緒安全的佇列有兩個方式 一種是使用阻塞演算法,另一種是使用非阻塞演算法。阻塞演算法 使用阻塞演算法的佇列可以用乙個鎖 入隊和出隊同一把鎖 或兩把鎖 入隊和出隊用不同的鎖 來實現。非阻塞的實現方式則可以使用迴圈cas的方式來實現。concurrentlinkedqueue非阻塞執行緒安全...

併發程式設計9 併發容器

解決併發情況下的容器執行緒安全問題 譬如 vector,hashtable,都是給予同步鎖實現的 concurrent包下的類,大部分都是使用系統底層的實現,類似於native public class test09 latch.countdown for thread t arr try catc...

同步容器與併發容器

同步容器 可以簡單地理解為通過synchronized來實現同步的容器,如果有多個執行緒呼叫同步容器的方法,它們將會序列執行。比如vector,hashtable 早起jdk的一部分 及collections.synchronized 等方法返回的容器。可以通過檢視vector,hashtable等...