我们可以了解到它是一个可重入锁,下面我们就一起看一下它的底层实现~
构造函数
我们在使用的时候,都是先new它,所以我们先看下它的构造函数,它主要有两个:
public ReentrantLock()
{
sync = new NonfairSync();
}
public ReentrantLock(boolean fair)
{
sync = fair ? new FairSync() : new NonfairSync();
}
从字面上看,它们之间的不同点在于fair,翻译过来就是公平的意思,大体可以猜到它是用来构建公平锁和非公平锁,在继续往下看源码之前,先给大家科普一下这两种锁。
公平锁 & 非公平锁
公平锁 多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。(例如银行办业务取号)
这种锁的优点很明显,每个线程都能够获取资源,缺点也很明显,如果某个线程阻塞了,其它线程也会阻塞,然而cpu唤醒开销很大,之前也给大家讲过
非公平锁 多个线程都去尝试获取锁,获取不到就进入等待队列,cpu也不用去唤醒
优缺点正好和上边相反,优点减少开销,缺点也很明显,可能会导致一直获取不到锁或长时间获取不到锁
好,有了基本概念之后,我们继续往下看
NonfairSync
首先,我们看下非公平锁,默认情况下,我们申请的都是非公平锁,也就是new ReentrantLock(),我们接着看源码
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,Sync是一个内容静态抽象类:
abstract static class Sync extends AbstractQueuedSynchronizer {…}
分为公平和非公平,使用AQS状态来表示持锁的次数,在构造函数初始化的时候都有sync = …,我们接着看NonfairSync。在使用的时候,我们调用了lock.lock()方法,它是ReentrantLock的一个实例方法
// 获取锁 public void lock() { sync.lock(); }
实际上内部还是调了syn