美文网首页
jdk并发组件分析(1)-ReentrantLock

jdk并发组件分析(1)-ReentrantLock

作者: zhangsean | 来源:发表于2019-12-19 22:15 被阅读0次

公平锁

上锁

acquire

上锁过程lock()->acquire(1)

acquire方法会tryAcquire尝试获取锁,获取不到开始入队。是否公平就体现在tryAcquire方法中。

public final void acquire(int arg) {
    //尝试获取锁,获取不到开始入队
    if (!tryAcquire(arg) &&
        //addWaiter构造队列,入队
        //acquireQueued循环抢占及休眠
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

tryAcquire判断

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
  
    //锁未占用
    if (c == 0) {
        //判断是否有前置等待线程
        //无前置等待线程 or 等待线程就是自己才可以抢占
        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;
}

hasQueuedPredecessors

public final boolean hasQueuedPredecessors() {
    Node t = tail;
    Node h = head;
    Node s;
    return h != t &&                                        //队列有内容
        ((s = h.next) == null || 
         s.thread != Thread.currentThread());   //队列第一个等待线程非自己
}

后面为addWaiteracquireQueued常规过程。代码就不分析了。

解锁

unlock

sync.release

  • tryRelease释放锁,返回是否完全释放
  • 完全释放后,unpark头结点的线程
public final boolean release(int arg) {
    //tryRelease返回锁是否完全释放
    if (tryRelease(arg)) {
        Node h = head;
      
        //正常不会是0,因为在acquireQueued过程已经设置为SIGNAL
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

unparkSuccessor

private void unparkSuccessor(Node node) {
    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);

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

非公平锁

上锁

lock直接尝试抢占

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

acquire代码和公平锁一致,只是抢占tryAcquire有些区别,就是暴力抢占,不判断第一个等待线程。

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

相关文章

网友评论

      本文标题:jdk并发组件分析(1)-ReentrantLock

      本文链接:https://www.haomeiwen.com/subject/puwvnctx.html