1. 程式人生 > >Java鎖之重入鎖(Reentrantlock)原理,公平鎖與非公平鎖

Java鎖之重入鎖(Reentrantlock)原理,公平鎖與非公平鎖

一個 star spa void 模板 ont thread fin 模式

1、特點:

已獲取鎖的線程再次請求鎖,可以直接獲取。

2、實現:

自定義內部類 Sync,繼承 AbstarctQueuedSynchronizer :

2.1、獲取鎖:lock()

a、公平鎖:

acquire(1)

b、非公平鎖:

if (compareAndSetState(0, 1))

//CAS,當前 state 為0,當前線程占有鎖:
  setExclusiveOwnerThread(Thread.currentThread());
else acquire(1);

b.1 AbstarctQueuedSynchronizer acquire(int acquires)

然後是 acquire(1) ——>調用父類 AbstarctQueuedSynchronizer acquire(int acquires)

public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}

即如果未獲取鎖,將請求鎖線程加入等待雙向隊列尾部。然後給當前線程發出中斷命令。

Node.EXCLUSIVE = null,

addWaiter(Node node) 將 null 加入等待隊列尾部,雙向隊列。

acquireQueued() 時候再次tryAcquire(arg)

b.2 ReetrantLock tryAcquire(int acquires)

ReetrantLock 繼承 自AbstarctQueuedSynchronizer 的 tryAcquire(int acquires) 如下(使用的 <模板模式>):

根據當前 state 判斷當前線程可否獲取鎖,tryAcquire(int acquires):

如果沒有線程持有當前鎖:if 0 == getState():

公平鎖

:CAS將 state 設置為當前占有次數,則將隊列中第一個線程喚醒,使其占有鎖。

非公平鎖:CAS將 state 設置為當前占有次數,直接使當前線程占有鎖。

如果當前線程持有鎖:else if current == getExclusiveOwnerThread(),則將其持有狀態值加上aquires。

2.2、釋放鎖:unlock() ——>AbstarctQueuedSynchronizer release(1) ——> sync.tryRelease(1)

state = getState -1

若當前線程非持有鎖線程,拋異常;

state == 0,當前持有鎖線程置空;

否則,setState(state)。

Java鎖之重入鎖(Reentrantlock)原理,公平鎖與非公平鎖