分析下ReentrantLock調用lock的fairSync版本

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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章