Java鎖之重入鎖(Reentrantlock)原理,公平鎖與非公平鎖
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 設置為當前占有次數,直接使當前線程占有鎖。
如果當前線程持有鎖:else if current == getExclusiveOwnerThread(),則將其持有狀態值加上aquires。
2.2、釋放鎖:unlock() ——>AbstarctQueuedSynchronizer release(1) ——> sync.tryRelease(1)
state = getState -1
若當前線程非持有鎖線程,拋異常;
state == 0,當前持有鎖線程置空;
否則,setState(state)。
Java鎖之重入鎖(Reentrantlock)原理,公平鎖與非公平鎖