ReentrantLock的实现原理是怎样的?详解

KLQ 2020-05-13 11:25:47 java常见问答 7784

大家对于ReentrantLock应该都不陌生吧,那么你对于它的实现原理又了解多少呢?下面就和小编一起来了解一下ReentrantLock的实现原理吧!

一、实现原理

ReentrantLock主要是通过CAS+CLH队列来实现。

它支持公平锁和非公平锁,两者的实现都是非常的类似。

ReentrantLock的基本实现:

首先通过CAS尝试获取锁

假如,这个时候已经有线程占据锁了的话,那么就加入CLH队列并且被挂起。

在锁被释放了之后,排在CLH队列队首的线程会被唤醒,之后,CAS再次尝试获取锁。

在这个时候,假如:

1、非公平锁

假如同时还有另外一个线程进来尝试获取,那么的话,就很有可能会让这个线程抢先获取。

2、公平锁

假如,同时还有另外一个线程进来尝试获取,那么,在它发现了自己不是在队列队首的话,就会排到队列队尾,由队首的线程获取到锁。

下面分别对这两个片段进行一下分析:

尝试获取锁时,会先调用下面的的方法。

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

假如,状态是0,那么就表示,这个时候没有人占有锁。

这个时候,尝试进行set,假如成功的话,那么就成功的占有了锁。

假如,状态不是0,就判断是不是当前的线程获取到了锁,假如是的话,那么就将状态+1,这样做的原因是因为,这个时候,就是当前线程,所以就不用CAS。

这个也是可重入锁的实现原理。

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

这个方法是在尝试获取锁失败加入CHL队尾之后,假如,发现了前序节点是head,那么,CAS再尝试获取一次,否则的话,就会根据前序节点的状态判断是不是需要阻塞,假如,是需要阻塞的话,那么就要调用LockSupport的park方法阻塞这个线程。

以上就是关于ReentrantLock的实现原理的简单介绍了,你都明白了吧!

请继续关注常见问题栏目,更多的java知识问答可以分享给大家。

推荐阅读:

ReentrentLock是什么?该如何实现?

sychronized和reentrantlock区别在哪里?都有什么用处?