juc · 2022-04-04 0

ReentrantLock 源码分析

1.非公平锁加锁

ReentrantLock 默认是非公平锁 NonfairSync

// ReentrantLock.java
public void lock() {
    sync.lock();
}

compareAndSetState(0, 1)AbstractQueuedSynchronizer 的方法,通过 CAS 把 AQS 的 state 值由 0 变为 1

如果state 实际值是 0,则修改为 1,并设置 AQS 的 exclusiveOwnerThread 的值为当前线程;

如果state 实际值不是 0,则执行 acquire(1)

// NonfairSync.java
final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

再次尝试抢占锁,如果 state 不是 0,则判断当前线程是否与 exclusiveOwnerThread 相同,相同则表示可重入,并把 state 值加 1

// Sync.java
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

addWaiter() 方法把线程封装到 Node 节点,添加到链表尾部,此链表的头节点是封装为null的Node节点

shouldParkAfterFailedAcquire() 设置此节点的前驱节点的 waitStatus 把 0 设置为 -1。整个链表的结果是,只有尾节点 waitStatus 为 0,其余节点的 waitStatus 为 -1

LockSupport.park(this) 阻塞当前线程

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

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;
}

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) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

private final boolean parkAndCheckInterrupt() {
    LockSupport.park(this);
    return Thread.interrupted();
}

2.非公平锁释放锁

// ReentrantLock.java
public void unlock() {
    sync.release(1);
}

tryRelease() 把 AQS 的 state 设置为 0,exclusiveOwnerThread 设置为 0

unparkSuccessor() 调用 LockSupport.unpark(),唤醒 head 节点的下一个节点

// AbstractQueuedSynchronizer.java
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

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;
    if (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;
    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)
        LockSupport.unpark(s.thread);
}
// Sync.java
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;
}

3.公平锁加锁

// FairSync.java
final void lock() {
    acquire(1);
}

假如 state 为 0,还需要判断链表是否有线程,如果有,则把这个线程节点添加到链表尾部

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;
}
// AbstractQueuedSynchronizer.java
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

4.公平锁与非公平锁体现

非公平锁,在尝试获得锁的过程中,多次判断 state 值,state 值为 0,则获得锁,否则加入到链表尾部

公平锁,在尝试获得锁的过程中,如果 state 为 0,还判断链表是否还有节点,如果有,则放到链表尾部