图1-1
根据上图可以知道,ReenTrantLock继承了Lock接口,Lock接口声明方法如下:
方法名 | 说明 | 抛出异常 |
---|---|---|
lock() | 一直阻塞获取锁,直到获取成功 | 无 |
lockInterruptibly() | 尝试获取锁,直到获取锁或者线程被中断 | InterruptedException |
tryLock() | 尝试获取空闲的锁,获取成功返回true,获取失败返回false,不会阻塞,立即返回 | 无 |
tryLock(long time, TimeUnit unit) | 尝试在time时间内获取空闲的锁,在等待时间内可以被中断 | InterruptedException |
unlock() | 释放锁 | 无 |
newCondition() | 返回当前锁的一个condition实例,用于条件性等待 | 无 |
1.ReentrantLock的部分方法
图2-1
Sync是NonfairSync 和FairSync 的父类,声明方法如下:
/** * 抽象方法,获取锁 */ abstract void lock(); /** * 实现非公平锁获取逻辑 */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); //父类同步器方法,获取当前同步状态,后续文章会分析 if (c == 0) {//状态等于0表示没有获取到锁 if (compareAndSetState(0, acquires)) { //CAS方式修改状态 setExclusiveOwnerThread(current); //修改成功后设置当前线程为锁的所有者 return true; } } else if (current == getExclusiveOwnerThread()) {//当前锁已被占用,判断是不是自己获取到了锁,锁重入 int nextc = c + acquires; //获取锁的计数器 if (nextc < 0) // overflow //因为是int类型,如果超过int最大值会溢出为负 throw new Error("Maximum lock count exceeded"); setState(nextc);//设置计数器为状态值 return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases;//释放锁,同步状态减int值 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); //如果当前相差不是锁的拥有者,抛出异常 boolean free = false; if (c == 0) { //如果同步状态值为0,表示锁已经释放成功 free = true; setExclusiveOwnerThread(null); // 设置锁的拥有线程为null } setState(c);//重新赋值同步状态 return free; } //判断当前线程是不是锁独占 protected final boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } //返回锁的ConditionObject实例 final ConditionObject newCondition() { return new ConditionObject(); } // Methods relayed from outer class //获取当前占有锁的线程 final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } //获取当前锁计数 final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } //判断是否获取到锁 final boolean isLocked() { return getState() != 0; //可以知道判断获取锁的关键就是是否不等于0 } 复制代码
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))//CAS获取锁 setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } 复制代码
lock()
和 tryAcquire(int acquires)
方法,其中和 tryAcquire(int acquires)
方法直接调用了父类的 nonfairTryAcquire(acquires)
,介绍父类的时候已经解析过,不清楚可以看上文Sync解析部分。根据lock源码发现,开始判断是否是第一次获取锁,如果获取锁成功,就把当前线程设置为锁的占有者,否则调用父类的 acquire(1)
方法(下一篇介绍同步器会介绍)。 static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; /**调用父类的acquire()方法*/ final void lock() { acquire(1); } /** * 尝试获取锁 */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); 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; } } 复制代码
!hasQueuedPredecessors()
判断,其实该方法就是判断是否有比当前线程等待最长时间的线程,如果没有,那么就尝试获取锁,获取成功后设置当前线程为锁的占有者,所以,公平与不公平就是是否按照时间等待来获取锁的,比如食堂吃饭,排队一个个来,这就是公平,如果有人插队,这就是不公平。 public ReentrantLock() { sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } public void lock() { sync.lock(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock() { return sync.nonfairTryAcquire(1); } //指定超时时间内获取锁,阻塞时间为timeout public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } public Condition newCondition() { return sync.newCondition(); } public int getHoldCount() { return sync.getHoldCount(); } public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } public final boolean isFair() { return sync instanceof FairSync; } 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(); } 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); } 复制代码
sync
,在介绍 sync
时候已经说过,它就是继承了 AbstractQueuedSynchronizer
同步器,很多方法都是直接调用父类同步器的方法,下一篇《java锁之ReentrantLock(二)》会重点解析 AbstractQueuedSynchronizer
同步器源码,分析同步器是如何依托于FIFO队列完成锁的机制。