ReentrantLock加鎖和釋放鎖底層原始碼分析

2021-10-10 08:07:20 字數 4791 閱讀 4257

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這麼...