ReentrantLock锁源码解析

Posted djcao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReentrantLock锁源码解析相关的知识,希望对你有一定的参考价值。

ReentrantLock的常用方法,lock、tryLock和unlock。

截图主要分析部分的源码如下:

技术图片
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;
        abstract void lock();
        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 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;
        }

        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don‘t need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

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

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

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

    public ReentrantLock() {
        sync = new NonfairSync();
    }

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    public void lock() {
        sync.lock();
    }

    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

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

}
View Code

一、类结构

1.ReentrantLock类有一个内部抽象静态类--Sync,Sync继承AbstractQueuedSychronizer(简称AQS),AQS为jdk并发锁的基类,

技术图片

2.ReentrantLock有两个构造函数,可以看到默认为NonfairSync(非公平实现),提供构造参数fair可供选择

    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

3.NonfairSync和FairSync为Sync的两种实现。具体差别在于重写的两个父类方法,lock()和tryAcquire()。具体差别在后面解释。

技术图片
static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

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

    /**
     * Sync object for fair locks
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don‘t grant access unless
         * recursive call or no waiters or is first.
         */
        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;
        }
    }
View Code

 

4.ReentrantLock的很多方法都是调用他的成员属性sync来实现的,sync在构造函数中完成初始化确定是公平实现还是非公平实现。

 a.ReentrantLock和Sync类为组合关系。又有点代理模式(委托模式)的意思

    b.ReentrantLock的两种不同锁实现只是覆盖了父类的方法,有AQS定义了锁实现的流程,不同子类的不同实现形成不同的功能,有点模板方法的感觉

public void lock() {
        sync.lock();
}
public void unlock() {
sync.release(1);
}

二、具体方法实现:

1.lock()方法

  a.追踪ReentrantLock的lock方法可以看到:

        final void lock() {
       // 调用Usafe类用cas(compare and swap)设置AQS的statu为1。 在设置state值时先判断state值是否为0,为0才设置1.
       // 当设置成功的时候调用AOS方法把当前线程保存为独占线程。
       // 当设置失败的时候调用acquire(1)函数,失败情况为,并发下,其他线程先设置为了1.
if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else
//该方法也是FairSync的lock方法的全部实现。
acquire(1); }

  b.acquire方法是AQS的获取锁的模板方法,tryAcquire为抽象方法由子类实现,addWaiter是把当前线程添加到队列中,

          acquireQueued是for死循环调用tryAcquire获取锁,会在调用两次后阻塞自己线程,并把当前线程所属节点的前置节点的waitStatus置为-1(Signal)。

          acquireQueued方法的出参表示执行完方法时的线程是否中断,如果为中断,会调用Thread.currentThread().interupt()。设置当前线程的中断标志

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

    c.公平锁实现的tryAcquire比非公平锁实现复杂,分析公平锁的实现,

          1.实现流程是,获取AQS的state,state=0表示还未获取了锁,并且当前的队列没有等待者,才尝试设置state为1.如果state不为0,如果当前锁由当前线程占用,则把state加1.实现可重入功能。

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

public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
 

 

   2.unlock实现:

       a.追踪ReentrantLock的unlock方法可以看到,具体实现代码在Sync中。

       b.tryRelease方法是把AQS的state值减一,采用cas算法,如果AQS的state是0,则返回true,表示当前线程完成释放了锁。

       c.当占有锁线程完成释放完锁时(每次重入都需要释放),判断头结点的waitStatus的值,如果非默认值,则表示有其他线程等待,唤醒第一个等待节点的线程。

       d.unparkSuccessor()方法就是唤醒链表中waitStatus不为-1(取消状态)的第一个等待节点。

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

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

 

 





















以上是关于ReentrantLock锁源码解析的主要内容,如果未能解决你的问题,请参考以下文章

Java 1.7 ReentrantLock源码解析

Java 1.7 ReentrantLock源码解析

AQS源码解析

JUC长征篇之ReentrantLock源码解析

ReentrantLock获取锁释放锁源码浅析

ReentrantLock源码之一lock方法解析(锁的获取)