reentranlock為可重入鎖:指為同乙個執行緒可以重複進入被鎖定的資源
reentranlock:分為公平鎖和非公平鎖 (預設非公平鎖)
公平鎖:所有的執行緒有序的排隊 lock lock = new reentranlock(true);
非公平鎖:執行緒阻塞時,先嘗試獲取鎖,沒有獲得再進行排隊等待 lock lock = new reentranlock();
原始碼類圖:
reentranlock 主要構成:
// 靜態內部類
private
final
sync sync;
/** * base of synchronization control for this lock. subclassed
* into fair and nonfair versions below. uses aqs state to
* represent the number of holds on the lock.
*/// 靜態內部內,繼承了abs,abstractqueuedsynchronizer :抽象的佇列同步器
// 是所有的juc並發包的基石,
abstract
static
class
sync
extends
abstractqueuedsynchronizer
*@return the predecessor of this node
*/// 獲取 前乙個節點
final
node
predecessor()
throws
nullpointerexception
node()
node
(thread thread,
node mode)
node
(thread thread,
int waitstatus)
}
reentranlock 非公平鎖加鎖原始碼分析:
// 對鎖的操作,基本都是對sync操作的封裝
public
void
lock()
reentrenlock 內部內 nonfairsync 非公平鎖 lock方法
static
final
class
nonfairsync
extends
sync
protected
final
boolean
tryacquire
(int acquires)
}
nonfairsync 中的 acquire(1);進入 abstractqueuedsynchronizer 的 acquire(1) 方法
public
final
void
acquire
(int arg)
tryacquire(arg) :
// abstractqueuedsynchronizer 父類方法,落地實現在子類中 即reentrenlock
// abstractqueuedsynchronizer 類
protected
boolean
tryacquire
(int arg)
// reentrenlock 類
protected
final
boolean
tryacquire
(int acquires)
// nonfairtryacquire(acquires);
// 引數 為 1
final
boolean
nonfairtryacquire
(int acquires)
}// 鎖被占用,判斷占用鎖的執行緒是否就是當前執行緒,如果是當前執行緒,代表獲取鎖為可重入鎖,意思就是同乙個執行緒多次加鎖
else
if(current ==
getexclusiveownerthread()
)// 獲取鎖失敗,也不是重入執行緒
return
false
;}
addwaiter(node.exclusive) 方法 node.exclusive 為null
node雙向佇列 的 頭節點為 哨兵節點,新的執行緒加入佇列實際為 從第二個節點加入
// abstractqueuedsynchronizer 類
private
node
addwaiter
(node mode)
}// 尾結點為 null ,初始化 佇列
enq(node)
;return node;
}// abstractqueuedsynchronizer 類 的 enq(node);方法
private
node
enq(
final
node node)
else}}
}
acquirequeued(node node, arg) // 此方法的主要目的為 :講新加入執行緒佇列的執行緒使用locksupport.park(),阻塞執行緒
// arg 為 1 來阻塞執行緒
final
boolean
acquirequeued
(final
node node,
int arg)
sethead
(node)
;// 講頭結點的下乙個節點設定為null,這樣這個節點就不引用其他物件,也不被其他物件引用,方便gc**
p.next =
null
;// help gc
// 阻塞執行緒失敗
failed =
false
;// 返回false
return interrupted;
}// 第一次自旋:如果前乙個節點不是頭節點,或者獲取鎖失敗,將前乙個node節點的waitstatus設定為 -1, shouldparkafte***iledacquire(p, node)返回 false
// 第二次自旋: shouldparkafte***iledacquire(p, node)返回ture, parkandcheckinterrupt(),將執行緒阻塞if(
shouldparkafte***iledacquire
(p, node)
&&parkandcheckinterrupt()
) interrupted =
true;}
}finally
}// shouldparkafte***iledacquire(p, node)
// 將前乙個執行緒node節點的waitstatus 設定為 -1
private
static
boolean
shouldparkafte***iledacquire
(node pred,
node node)
while
(pred.waitstatus >0)
; pred.next = node;
}else
return
false;}
// parkandcheckinterrupt();執行緒阻塞的地方
private
final
boolean
parkandcheckinterrupt()
unlock原始碼分析
// 依然呼叫sync內部內的方法 release(1)
public
void
unlock()
// abstractqueuedsynchronizer 類中的方法
public
final
boolean
release
(int arg)
return
false;}
// reentrenlock tryrelease(arg)
protected
final
boolean
tryrelease
(int releases)
// 設定 鎖的狀態
// 0 代表完全釋放鎖,>0表示當前執行緒進行了多次重入鎖,需要對應次數的釋放鎖,本次只代表釋放一次鎖
setstate
(c);
return free;
}// abstractqueuedsynchronizer unparksuccessor(h);
// node 引數為 佇列中 頭節點
private
void
unparksuccessor
(node node)
if(s !=
null
)// 喚醒第二個節點中的執行緒,進行搶鎖
locksupport
.unpark
(s.thread)
;}
從ReentrantLock加鎖解鎖角度分析AQS
本文用於記錄在學習aqs時,以reentrantlock為切入點,深入原始碼分析reentrantlock的加鎖和解鎖過程。同步器aqs的主要使用方式是繼承,子類通過繼承同步器並實現它的抽象方法來管理同步狀態 通常鎖或者同步元件內部會實現乙個sync類 該類是乙個靜態內部類 然後讓sync類去繼承a...
ReentrantLock實現同步
reentrantlock 也可以實現synchronized方法 塊的同步效果。reentrantlock 實現同步 如下 1 新建乙個service類 public class myservice public static void methodb 2 新建乙個測試類 public class...
ReentrantLock之unlock方法分析
public void unlock public final boolean release int arg return false release 1 嘗試在當前鎖的鎖定計數 state 值上減1。成功返回true,否則返回false。當然在release 方法中不僅僅只是將state 1這麼...