ReentrantLock源码解读(一)

我们先跟踪非公平锁加锁和释放锁的大概流程,有一个基本的印象。

public class LockTest {
    private Lock lock = new ReentrantLock();
    public void lockTest() {
        lock.lock();
        try {
            System.out.println("lock test");
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        LockTest test = new LockTest();
        new Thread() {
            @Override
            public void run() {
                test.lockTest();
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                test.lockTest();
            }
        }.start();
    }
}

先看下默认的构造方法:

    /**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.   
     */
    // 创建一个实例,等同于调用 new ReentrantLock(false),返回非公平锁的实例
    public ReentrantLock() {
        sync = new NonfairSync();
    }

在上面的构造方法中,创建了NonfairSync 对象赋值给成员变量 sync

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

由此可以看出NonfairSync 是Sync 的一个子类

    /**
     * Sync object for non-fair locks
     */
    // 非公平锁的同步对象
    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 是什么东西

    /**
     * Base of synchronization control for this lock. Subclassed
     * into fair and nonfair versions below. Uses AQS state to
     * represent the number of holds on the lock.
     */
    // 锁同步控制的基础。子类包括公平锁和非公平锁。利用AQS 的状态来表示锁持有的次数
    abstract static class Sync extends AbstractQueuedSynchronizer {
        ...
        ...
        ...
    }

Sync 继承了AbstractQueuedSynchronizer,也就是上面类注释中的AQS,并且知道锁的控制流程跟AQS 的state 有关。

再来理一下,创建一个ReentrantLock,会间接持有一个AbstractQueuedSynchronizer 实现类的引用,也就是我们常说的AQS,接下来的加锁跟释放锁操作,都跟AQS 或者其子类有关。

先看一下ReentrantLock.lock() 方法

    /**
     * Acquires the lock.
    //获得锁
     *
     * <p>Acquires the lock if it is not held by another thread and returns
     * immediately, setting the lock hold count to one.
    //如果锁没有被其他线程持有就可以获得,并且立即返回,然后设置锁的持有计数为1
     *
     * <p>If the current thread already holds the lock then the hold
     * count is incremented by one and the method returns immediately.
    //如果当前线程已经获得锁,锁的持有计数就会增加1,并且立即返回
     *
     * <p>If the lock is held by another thread then the
     * current thread becomes disabled for thread scheduling
     * purposes and lies dormant until the lock has been acquired,
     * at which time the lock hold count is set to one.
    // 如果锁被其他线程持有,当前线程就会被禁用并且休眠,直到锁被获取,获取到之后,锁的持有计数设置为1
     */
    public void lock() {
        sync.lock();
    }

跟踪代码,发现调用的是NonfairSync.lock(),看下代码

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

方法compareAndSetState(0, 1) 来自父类AQS,实际上调用的是CAS

    /**
     * Atomically sets synchronization state to the given updated
     * value if the current state value equals the expected value.
     * This operation has memory semantics of a {@code volatile} read
     * and write.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that the actual
     *         value was not equal to the expected value.
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

这下对于获取锁这个操作就比较明朗了,底层使用CAS,保证线程安全。线程A 进来先调用compareAndSetState(0, 1),判断当前锁的计数状态是不是0,是0的话,就将锁的计数状态变成1,返回true,相当于获得一把锁,此时线程B进来,继续调用compareAndSetState(0, 1),由于此时锁的计数状态是1,不等于0,返回false,相当于锁获取失败,走到acquire(1) 代码分支,进行排队,acquire(1) 方法先不讲细节,只需要先知道在这个方法中,其他线程会一直排队,直到获取锁。

到此大方向跟完了ReentrantLock.lock() 方法,接下来继续跟踪ReentrantLock.unlock()

    /**
     * Attempts to release this lock.
    //尝试释放锁
     *
     * <p>If the current thread is the holder of this lock then the hold
     * count is decremented.  If the hold count is now zero then the lock
     * is released.  If the current thread is not the holder of this
     * lock then {@link IllegalMonitorStateException} is thrown.
    //如果当前线程持有锁,则锁的计数状态-1。如果锁的计数状态为0,说明锁已经释放了。如果当前线程没持有锁,就会抛异常
     *
     * @throws IllegalMonitorStateException if the current thread does not
     *         hold this lock
     */
    public void unlock() {
        sync.release(1);
    }

继续跟下去,发现调用的是AQS 的release() 方法

    /**
     * Releases in exclusive mode.  Implemented by unblocking one or
     * more threads if {@link #tryRelease} returns true.
     * This method can be used to implement method {@link Lock#unlock}.
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryRelease} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @return the value returned from {@link #tryRelease}
     */
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

继续跟tryRelease(arg) 方法,这个方法必须是子类实现的,因此我们去看下Sync 中的实现

abstract static class Sync extends AbstractQueuedSynchronizer {
    ...
    ...
        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;
        }
}

tryRelease 方法中,将锁计数状态减少并重新赋值。也就是说,lock() 方法会增加锁计数状态,unlock() 会减少锁的计数状态,刚好印证前面说的锁的控制流程跟AQS 中的state 有关。

本章先大致跟踪一下非公平锁加锁跟释放锁的流程,并没有深入跟踪比如锁的排队机制、公平锁和公平锁各自的实现差异、锁可打断的原理实现等,后续咱们带着这些疑问一个一个去跟踪。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值