ReentrantLock

ReentrantLock分为公平锁和非公平锁,从有参构造器中可以看出,公平锁对象创建是内部类:new NonfairSync()

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
NonfairSync的源码如下所示,先分析lock()方法,从该方法可以看出,所谓的上锁过程,就是将AQS中的变量status设置为1,修改成功,便将锁的持有者设为本线程。
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);
        }
    }

如果获取失败,则会调用父类AQS中的acquire(1)方法尝试获取锁,NonfairSync中重写了acquire(int arg)中的tryAcquire(arg)方法,通过nonfairTryAcquire(acquires)方法来获取锁:

这个方法里,当前线程会尝试获取锁,分为三种情况:第一种,当前锁未被其它线程持有,当前线程进行第一次锁竞争;第二种,当前锁已被占用,判断持锁线程是不是自己,如果是,则直接修改锁状态(加1),这便是可重入锁;如果前两种都不满足,那么获取锁失败,返回false,进入AQS的CLH锁队列中等待被唤醒。
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState(); //获取AQS中的状态值
            //state为0,表示此时没有线程持有锁,当前线程可以去尝试获取锁
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //如果state不为0,此时判断持锁线程是不是当前线程,因为ReentrantLock是可重入锁,如果是当前线程,state加1
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                //小于0,表示锁重入数超出了int范围,
                if (nextc < 0) 
                    throw new Error("Maximum lock count exceeded");     
                //这里不用CAS,是因为同一个线程修改state,无安全问题
                setState(nextc);
                return true;
            }
            return false;
        }

SanPiBrother
24 声望3 粉丝

菜鸡的救赎之路