reentrantLock調用lock的fairSync版本
1 reentrantLock調用lock
public void lock() {
sync.lock(); -> 2 :調用sync的lock方法,選的fairsync作爲例子
}
2 調用acquire方法,嘗試獲取鎖
final void lock() {
acquire(1); -> 3
}
3 (1)獲取鎖成功,退出. (2)獲取鎖失敗,添加node至隊列尾部
public final void acquire(int arg) {
if (!tryAcquire(arg) && -->4
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) ---->6.(5)
selfInterrupt();
}
4 原子地獲取鎖,(1)獲取成功則將state由0添加至1.(2) 重入則添加state計數器,(3)否則失敗
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
5 將信息爲當前線程的Node原子性地添加至隊列尾部.(1).尾部不爲空則cas操作尾部引用設置爲當前node.並且將之前的尾部的next設置爲當前node. (2)尾部爲空則設置頭尾爲一個新的Node,然後設置當前node爲尾,然後將當前node設置爲尾
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
6 如果node的前節點爲head,如果獲取鎖權限成功,則將頭節點設置爲當前節點,並且釋放前節點,返回interrupted狀態(設置interupted用)
如果前節點不爲head或者獲取鎖權限失敗, 則根據前驅節點的waitStatus如果爲signal則阻塞當前線程,如果不爲signal則設置爲signal繼續循環
循環
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && ---->7
parkAndCheckInterrupt()) ---->8
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
7 前驅節點爲signl則直接安全的返回true… return
如果前驅節點爲cancel,則全部取消直到不需要取消的節點,然後將節點的後繼者設置爲當前節點. return false
否則cas原子性地將前節點地statu設置爲signal return false
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
8 locksupport 將當前線程的blocker設置爲當前locksupport .阻塞當前線程. 醒了就設置爲空.傳遞interupted狀態
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn't need a write barrier here.
UNSAFE.putObject(t, parkBlockerOffset, arg);
}