ReentrantLock源码分析(一)

一、简介

       众所周知,Java并发组件中的一个重要框架就是AQS,简称同步器。全称AbstractQueuedSynchronizer,它是基于模板方法模式实现的。也就是说大体算法框架已经写好了,具体的一些细节需要用户去实现。AQS中有5个方法是用户根据需要实现的(排它锁与否):

protected boolean tryRelease(int arg) {
    throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
    throw new UnsupportedOperationException();
}
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
    throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
    throw new UnsupportedOperationException();
}

二、ReentrantLock的骨架

       ReentrantLock是排它锁,需要实现上面的两个排它方式的方法。看一下ReentrantLock的内部构造:
       ReentrantLock锁依赖于Sync:

public class ReentrantLock implements Lock {
    ...
    private final Sync sync;
    ...
}

并在内部实现了Sync:

abstract static class Sync extends AbstractQueuedSynchronizer {
    abstract void lock();
    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        //c = 0 的时候直接获取锁,非公平的,没有去查看队列前面
        //还有没有其他线程在获得锁
        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){...}
    protected final boolean isHeldExclusively() {...} 
    ...
}

分析:
       ReentrantLock 是独占锁,按理说需要实现抽象类 AbstractQueuedSynchronizer 中的以下两种方法: tryRelease 和tryAcquire。
       从上面可以看出,它只实现了其中一个,接着往下看可以发现,tryAcquire(int arg) 在子类中实现了。Sync有两个子类,分别是:

static final class NonfairSync extends Sync {...}
static final class FairSync extends Sync {...}

即非公平锁和公平锁的组件。
1、非公平锁:

static final class NonfairSync extends Sync {
    /**
      * 1)首先基于CAS将state(锁数量)从0设置为1,如果设置成功,
      * 设置当前线程为独占锁的线程;-->请求成功-->第一次插队
      * 即在尝试的过程中,已经被其他线程先一步占有了锁),
      * 这个时候当前线程执行acquire(1)方法
      */
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}

分析:
       Sync默认实现了非公平锁获取的方法。在NonfairSync中,实现了boolean tryAcquire(int acquires),即以非公平的方式获取锁。上面的acquire(1)函数在AQS中已经实现了,其中就调用了这里实现的boolean tryAcquire(int acquires)方法。
2、公平锁:

static final class FairSync extends Sync {
    final void lock() {
        acquire(1);
    }
    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        //c为0的时候可以获取锁
        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;
    }
}

分析:
       在FairSync中,实现了boolean tryAcquire(int acquires),即以公平的方式获取锁。注意和 Sync 中的 final boolean nonfairTryAcquire(int acquires) 作比较。Lock()里面的acquire(1)函数在AQS中已经实现了,其中就调用了这里实现的boolean tryAcquire(int acquires)方法。
       好了,至此上面所说的两个函数都实现了: tryRelease,tryAcquire。

三、具体实现

       既然Sync组件已经写好了,那么ReentrantLock中的方法就可以使用它了。上面说到,ReentrantLock依赖组件Sync,即:

public class ReentrantLock implements Lock {
    ...
    private final Sync sync;
    ...
}

下面看一下ReentrantLock的具体实现:
1、构造函数:有两个,默认是非公平的。

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

2、获得锁:

//不响应中断地获取锁
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));
}   

3、释放锁

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

4、条件变量

public Condition newCondition() {
    return sync.newCondition();
}

5、锁相关的工具性质的方法

//当前锁被当前线程持有的次数
public int getHoldCount() {
    return sync.getHoldCount();
}
//当前线程是否持有该锁
public boolean isHeldByCurrentThread() {
    return sync.isHeldExclusively();
}
//该锁是否被锁
public boolean isLocked() {
    return sync.isLocked();
}
//是否为公平锁
public final boolean isFair() {
    return sync instanceof FairSync;
}
//返回持有该锁的线程,没有的话返回null
protected Thread getOwner() {
    return sync.getOwner();
}
//查询是否有线程在等待获取此锁
public final boolean hasQueuedThreads() {
    return sync.hasQueuedThreads();
}
//查询给定的线程是否在等待获取此锁
public final boolean hasQueuedThread(Thread thread) {
    return sync.isQueued(thread);
}
//返回等待此锁的线程数目的估计值
public final int getQueueLength() {
    return sync.getQueueLength();
}
//返回一个集合,该集合包含可能正在等待此锁的线程,因为在构造该结果集的
//时候,线程可能会改变,所以这个集合也只是个估计。
protected Collection<Thread> getQueuedThreads() {
    return sync.getQueuedThreads();
}

6、条件变量相关工具类方法

public boolean hasWaiters(Condition condition) {
    if (condition == null)
        throw new NullPointerException();
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
    return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public int getWaitQueueLength(Condition condition) {
    if (condition == null)
        throw new NullPointerException();
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
        throw new IllegalArgumentException("not owner");
    return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
protected Collection<Thread> getWaitingThreads(Condition condition) {
    if (condition == null)
        throw new NullPointerException();
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
        throw new IllegalArgumentException("not owner");
    return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}

四、最后

       可以看到,ReentrantLock方法的实现全部是依靠Sync的方法。而Sync又是继承了AQS,所以重点就是分析AQS。
       这篇文章只是分析个大概,并没有去详细剖析,主要是为了了解ReentrantLock的大致结构,掌握大局。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值