ReentrantLock鎖的釋放
阿新 • • 發佈:2018-03-26
IT nod his port == 一次 ive 令牌 next
一:代碼
reentrantLock.unlock();
雖然只有一句,但是源碼卻比較多:
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }
這個方法中各個方法意義:
1、tryRelease(arg),嘗試去解鎖,通過改變state的值來釋放鎖,如果state的值變成了0,那麽返回true,則鎖釋放完成,否則返回false;
2、unparkSuccessor,如果繼任的線程節點存在,就去喚醒這個繼任的節點。
二、首先調用的是sync類下的tryRelease方法
protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
首先拿到重入的次數,釋放一次重入就減少一次,只有重入的次數減少到0時,才返回true。
三、unparkSuccessor源碼:
/** * Wakes up node‘s successor, if one exists. * * @param node the node */ private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. */ int ws = node.waitStatus; // 獲取頭節點的waitStatus if (ws < 0) // 如果頭節點的ws狀態與預期的一樣,就把頭節點的ws設置為0 compareAndSetWaitStatus(node, ws, 0); /* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ Node s = node.next; // 如果頭節點的繼任節點時空,或者被取消了,那麽就不會有節點掛在這個繼任節點下面, // 那麽就從尾部一直往前追溯,直到t.waitStatus <= 0 if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) // 釋放鎖,令牌permit被下一個線程節點拿到。 LockSupport.unpark(s.thread); }
ReentrantLock鎖的釋放