多執行緒與併發6 併發容器

2022-09-12 16:39:37 字數 3278 閱讀 3966

hashtable所以方法預設加sychronized,

hashmap預設沒有加鎖,

而synchronizedhashmap預設是collections.synchronizedmap(mapmap)返回乙個同步map。

currenthashmap是多線**正用的,本來是拉鍊表,jdk1.8後變成紅黑樹.

concurrenthashmap相比hashmap而言,是多執行緒安全的,其底層資料與hashmap的資料結構相同,資料結構如下:

concurrenthashmap的資料結構(陣列+鍊錶+紅黑樹),桶中的結構可能是鍊錶,也可能是紅黑樹,紅黑樹是為了提高查詢效率。

jdk1.5中的實現

concurrenthashmap使用的是分段鎖技術,將concurrenthashmap將鎖一段一段的儲存,然後給每一段資料配一把鎖(segment),當乙個執行緒占用一把鎖(segment)訪問其中一段資料的時候,其他段的資料也能被其它的執行緒訪問,預設分配16個segment。預設比hashtable效率提高16倍。

concurrenthashmap的結構圖如下(網友貢獻的圖,哈):

jdk1.8中的實現

concurrenthashmap取消了segment分段鎖,而採用cas和synchronized來保證併發安全。資料結構跟hashmap1.8的結構一樣,陣列+鍊錶/紅黑二叉樹

synchronized只鎖定當前鍊錶或紅黑二叉樹的首節點,這樣只要hash不衝突,就不會產生併發,效率又提公升n倍。

jdk1.8的concurrenthashmap的結構圖如下:

treebin:紅黑二叉樹節點

node:鍊錶節點

concurrenthashmap 類結構參照hashmap,這裡列出hashmap沒有的幾個屬性。

/**

* table initialization and resizing control. when negative, the

* table is being initialized or resized: -1 for initialization,

* else -(1 + the number of active resizing threads). otherwise,

* when table is null, holds the initial table size to use upon

* creation, or 0 for default. after initialization, holds the

* next element count value upon which to resize the table.

hash表初始化或擴容時的乙個控制位標識量。

負數代表正在進行初始化或擴容操作

-1代表正在初始化

-n 表示有n-1個執行緒正在進行擴容操作

正數或0代表hash表還沒有被初始化,這個數值表示初始化或下一次進行擴容的大小

*/private transient volatile int sizectl;

// 以下兩個是用來控制擴容的時候 單執行緒進入的變數

/*** the number of bits used for generation stamp in sizectl.

* must be at least 6 for 32bit arrays.

*/private static int resize_stamp_bits = 16;

/*** the bit shift for recording size stamp in sizectl.

*/private static final int resize_stamp_shift = 32 - resize_stamp_bits;

/** encodings for node hash fields. see above for explanation.

*/static final int moved = -1; // hash值是-1,表示這是乙個forwardnode節點

static final int treebin = -2; // hash值是-2 表示這時乙個treebin節點

分析**主要目的:分析是如果利用cas和synchronized進行高效的同步更新資料。下面插入資料原始碼:

public v put(k key, v value) 

/** implementation for put and putifabsent */

final v putval(k key, v value, boolean onlyifabsent)

//檢查到內部正在移動元素(node 陣列擴容)

else if ((fh = f.hash) == moved)

//幫助它擴容

tab = helptransfer(tab, f);

else {

v oldval = null;

//鎖住鍊錶或紅黑二叉樹的頭結點

synchronized (f) {

//判斷f是否是鍊錶的頭結點

if (tabat(tab, i) == f) {

//如果fh>=0 是鍊錶節點

if (fh >= 0) {

bincount = 1;

//遍歷鍊錶所有節點

for (node e = f;; ++bincount) {

k ek;

//如果節點存在,則更新value

if (e.hash == hash &&

((ek = e.key) == key ||

(ek != null && key.

多執行緒與高併發7 容器

queue佇列 主要就是為高併發而存在,有進有出。deque雙關佇列 頭和尾都可以訪問 blockingqueue阻塞佇列 priorityqueue優先佇列 按照順序先入先出 delayqueue延遲佇列 佇列中的物件只有到期之後才能被取走 一代同步容器,所有的方法均上鎖,基本不用 hashtab...

併發與多執行緒

標頭檔案 include c 11建立執行緒 thread th myfunc 建立乙個子執行緒,並且子執行緒開始執行,引數為可呼叫物件,可以是函式,仿函式,lambda表示式,下面給出例子示例 void myfunc class myclass void func intmain thread t...

多執行緒與併發

執行緒的部分功能就是實現併發,多個執行緒在每個執行緒上都可以執行小段的 處理器很快的在各個執行緒間進行切換,像是在同時執行,其實所有的 ios 裝置都還有第二個處理器,顯示介面卡 gpu 與顯示相關的 都由 gpu 獨立於主處理器之外執行.主線程自動有乙個執行迴圈 run loop 乙個run lo...