ReentrantLock公平锁与非公平锁源码分析

ReentrantLock公平锁与非公平锁源码分析

获取锁的方式

非公平锁尝试获得锁的代码

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

公平锁尝试获得锁的代码

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() &&    //公平锁的获取多了这个判断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());
    }

​ 该代码主要判断当前节点是否有前驱节点的判断,如果有则表明 !hasQueuedPredecessors() == true,则表示前面还有更早的线程在请求锁,需要等待前驱线程获取锁并且释放锁后才能继续获取锁;

​ 看下源码里具体是如何判断的,我们先来看下 return 的是什么,主要是三个条件的判断:

  1. h != t
  2. (s = h.next) == null
  3. s.thread != Thread.currentThread()

​ 1、如果h==t成立,h和t均为null或是同一个具体的节点,无后继节点,返回false。

​ 2、如果 h!=t 成立,head.next是否为null,如果为null,返回true。什么情况下h!=t的同时h.next==null ?有其他线程第一次正在入队时,可能会出现。见AQS的enq方法,compareAndSetHead(node)完成,还没执行tail=head语句时,此时tail=null,head=newNode,head.next=null

​ 3、如果 h!=t 成立,head.next != null,则判断head.next是否是当前线程,如果是返回false,否则返回true(head节点是获取到锁的节点,但是任意时刻head节点可能占用着锁,也可能释放了锁(unlock()),未被阻塞的head.next节点对应的线程在任意时刻都是有必要去尝试获取锁)

​ 总的来时,就是公平锁会判断队列里是否有排队的线程,并且头结点的下一个线程是否为当前尝试获取锁的线程,如果不是当前线程则不去进行CAS尝试。

未完待续…


文章作者: ClarkRao
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ClarkRao !
  目录