深入ReentrantLock源码解析

ReentrantLock是基于AQS实现的,它提供了公平锁与非公平锁两种策略,当然这两种策略都是抢占式的。其核心代码是对AQS的公平、非公平的实现,下面我们来看其核心代码:

  1. 内部类Sync,该类定义为抽象类,并继承自AbstractQueuedSynchronizer,它还会被NonfairSync(非公平策略)与FairSync(公平策略)两个类继承。主要关注nonfairTryAcquire方法与tryRelease方法

        // Sync类继承自AbstractQueuedSynchronizer,
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860L;
    
            // ReentrantLock的lock方法就是调用这个方法,由子类实现。
            abstract void lock();
    
    
            // 这个方法提供了对非公平锁策略的实现
            final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
    
                // 只有当state为0时,才可以竞争锁
                if (c == 0) {
                    // 与公平锁的主要区别在这里,下面会提供公平锁的实现。
                    // 非公平锁直接用CAS尝试修改AQS的state,而没考虑排队情况,因此是不公平的
                    // 公平锁只会让处于head的线程去修改state,相当于排队了,因此是公平的
                    // 如果state修改成功,会通过setExclusiveOwnerThread方法将当前线程设置为exclusiveOwnerThread,表示竞争成功
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                // 注意,这里实现了可重入性!这种情况是state!=0,即当前锁是被线程占有的,但是如果占有该锁的线程就是当前线程,那么还是能够修改state
                // 获取到1次,state=acquires
                // 获取到2次,state=2*acquires
                // 依次类推
                // 在release的时候也会一层一层的减回去,因此要保证lock与unlock次数一样
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;//这里会state累加
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
    
            // 该方法提供了锁的释放,不论是公平还是不公平锁,都用这个实现
            // 这里release的值与tryAcquire中acquires的值应该相等,不然会出现锁完全释放后,state!=0的情况,那就凉了。。。
            protected final boolean tryRelease(int releases) {
                int c = getState() - releases;
    
                // 保证释放锁的线程,必须拥有锁,不然抛出异常
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
    
                // 如果释放完之后,state的值确实为0,那么将获得锁的线程设置为null
                // 注意,这里也支持重入性,如果释放完之后,c不为0,那么当前线程还可以继续释放。
                boolean free = false;
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }
    
            // 这是对isHeldExclusively实现,即判断当前线程是否exclusiveOwnerThread
            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();
            }
    
            // 对Condition的支持
            final ConditionObject newCondition() {
                return new ConditionObject();
            }
    
            // 其它方法很简单省略...
        }
  2. NonfairSync,继承自Sync,非公平锁策略,实现很简单,因为Sync已经都实现了非公平的策略

        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            /**
             * 实现lock方法。先通过compareAndSetState尝试获取一次,如果成功则获取锁。
             * 否则走acquire,详见AbstractQueuedSynchronizer源码解析。
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            // 重写tryAcquire,直接调用Sync的nonfairTryAcquire方法。
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
  3. FairSync,继承自Sync,公平策略。需要实现公平策略的tryAcquire

        static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            // 区别1:这里没有先尝试获取一次,因为公平模式必须要排队。而非公平模式不用考虑队列,所以可以先使用compareAndSetState获取一次
            final void lock() {
                acquire(1);
            }
    
            /**
             * 公平锁策略
             */
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    // 主要区别在这里,在竞争之前,先判断!hasQueuedPredecessors()
                    // 如果当前线程在队首,则hasQueuedPredecessors返回false
                    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;
            }
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值