AQS reentrantlock加鎖流程

2021-10-09 14:38:58 字數 2874 閱讀 7482

aqs 與reentrantlock ,reentrantreadwritelock 解析

預備知識aqs 大致內部結構如下圖所示

記憶體值v、舊的預期值a、要修改的值b,當且僅當預期值a和記憶體值v相同時(條件),將記憶體值修改為b並返回true,否則條件不符合返回false。條件不符合說明該變數已經被其它執行緒更新了。

名詞解釋:

node head/tail: 維護的是執行緒的乙個fifo佇列;

state: volatile修飾的乙個常量(記憶體可見性,防止指令重排序);

exclusiveownerthread: 當前執行緒持有者如t1執行緒;

重要方法:

tryacquire :嘗試加鎖抽象方法需要自己實現重點看下面 reentrantlock解析;

acquire:當嘗試加鎖失敗,會進入fifo佇列排隊;

tryrelease: 抽象方法子類實現;

release: 解鎖操作;

reentrantlock 分為公平與非公平鎖 預設非公平鎖

建立公平鎖

reentrantlock lock =new reentrantlock(true);//公平鎖

reentrantlock lock =new reentrantlock();//非公平鎖

加鎖過程:

/**

* 加鎖

*/final

void

lock()

/** * 呼叫此方法加鎖

*/public

final

void

acquire

(int arg)

}/**

* 公平鎖 分析tryacquire 方法

* 非公平與公平鎖的區別是缺少hasqueuedpredecessors()此方法

* 非公平鎖直接設定值搶鎖

*/protected

final

boolean

tryacquire

(int acquires)

}//判斷當前執行緒是否等於自己 為自己 表示鎖的可重入 state + 1

else

if(current ==

getexclusiveownerthread()

)return

false;}

/** * 1、第一種可能如果執行緒第一次進來 前面沒有元素 那麼返回false

* 2、如果 h != t 為true 則表示佇列裡面》=2個元素

* 3、看自己是否為第二個節點,若是第二個或者是下乙個(不是當前執行緒)則排隊不拿鎖

*/public

final

boolean

hasqueuedpredecessors()

/** * mode 傳過來的值 ==null

* 只有拿鎖失敗 才會加入佇列等待喚醒

* 這裡可以看成t1 搶鎖成功 t2 失敗

*/private node addwaiter

(node mode)

}enq

(node)

;return node;

}/**

* 迴圈比較

* 形成佇列

* node 代表t2 進來

*/private node enq

(final node node)

else}}

}/**

* 判斷執行緒是否需要睡眠

*/final

boolean

acquirequeued

(final node node,

int arg)

//第一次 false 第二次遍歷時候true 則走&&後面方法park 當前執行緒if(

shouldparkafte***iledacquire

(p, node)

&&parkandcheckinterrupt()

) interrupted =

true;}

}finally

}/**

* 搶鎖失敗 後則需要執行緒park

*/private

static

boolean

shouldparkafte***iledacquire

(node pred, node node)

while

(pred.waitstatus >0)

; pred.next = node;

}else

return

false

;}

最終enq 執行後的示意圖如下

t.next 指向t2 t2.prev指向t 構成雙向佇列

公平鎖 : 需要排隊依次進行

非公平鎖:競爭搶鎖

重量級鎖:如synchronized

輕量級鎖:如reentrantlock

自旋鎖:如reentrantlock /reentrantreadwritelock

可重入鎖:reentrantlock、synchronized鎖的可重入解釋是當乙個方法用synchronized修飾了method1 裡面呼叫了synchronized 修飾的method2 那麼方法二是可以執行的。

讀寫鎖:reentrantreadwritelock 讀讀並行 ,讀寫互斥 ,寫寫互斥,讀鎖不能公升級為寫鎖,

mysql自定義加鎖 為MySQL加鎖?

在日常操作中,update insert delete innodb會自動給涉及的資料集加排他鎖,一般的 select 一般是不加任何鎖的。我們可以使用以下方式顯示的為 select 加鎖。共享鎖 select from table name where id 10 lock in share mo...

atomic 加鎖操作

property atomic,strong nsstring name setter void setname name getter void name 為什麼加鎖 多執行緒的安全隱患 資源共享 一塊資源可能會被多個執行緒共享,也就是多個執行緒可能會訪問同一塊資源 比如多個執行緒訪問同乙個物件 ...

索引與加鎖

索引與加鎖 索引對於innodb非常重要,因為它可以讓查詢鎖更少的元組。這點十分重要,因為mysql 5.0中,innodb直到事務提交時才會解鎖。有兩個方面的原因 首先,即使innodb行級鎖的開銷非常高效,記憶體開銷也較小,但不管怎麼樣,還是存在開銷。其次,對不需要的元組的加鎖,會增加鎖的開銷,...