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行級鎖的開銷非常高效,記憶體開銷也較小,但不管怎麼樣,還是存在開銷。其次,對不需要的元組的加鎖,會增加鎖的開銷,...