ReentrantLock 重入锁是对 synchronized 的一种补充,ReentrantLock 提供了可定时、可轮询的与可中断的锁获取操做,公平队列,以及非块结构的锁。与 synchronized 相比, ReentrantLock 更加灵活可控,伸缩性更好。ReentrantLock 的非公平锁性能也比 synchronized 更好。
经过对 CAS 的了解,咱们知道 CAS 底层也是经过排它锁实现的,只不过 CAS 是 CPU 触发的,效率更高。ReentrantLock 实现方式和 AtomicInteger 方式相似,不过 ReentrantLock 借助 AbstractQueuedSynchronizer 类来实现独占锁的功能。
ReentrantLock 主要方法以下:java
ReentrantLock 结构:node
public class ReentrantLock implements Lock, Serializable { private static final long serialVersionUID = 7373984872572414699L; private final ReentrantLock.Sync sync; public ReentrantLock() { this.sync = new ReentrantLock.NonfairSync(); } public ReentrantLock(boolean var1) { this.sync = (ReentrantLock.Sync)(var1?new ReentrantLock.FairSync():new ReentrantLock.NonfairSync()); } public void lock() { this.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)); } public void unlock() { sync.release(1); } }
ReentrantLock 获取锁能够经过 lock 和 tryLock 获取,lock 方法获取时,若是所没被占用直接获取,若是被本线程占用,则直接获取,不然加入等待队列,并阻塞线程;tryLock 方法获取时,若是所没被占用直接获取,若是被本线程占用,也直接获取,若是被其余线程占用,则马上返回失败。
从 ReentrantLock 中咱们能够看到 ReentrantLock 的锁是经过 Sync 这个类完成的,Sync 则继承自 AbstractQueuedSynchronizer,AQS 是独占锁和共享锁的父类,经过 AQS 的 compareAndSetState 方法来进行加锁从而实现独占锁的功能。
Sync 有两个子类,分别是 FairSync 和 NonfairSync。
NonfairSync 结构:less
/** * Sync object for non-fair locks */ 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); } }
NonfairSync 则先尝试获取锁,若是获取失败则再加入等待队列。ReentrantLock 默认是非公平锁。
FairSync 结构:函数
/** * Sync object for fair locks */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ 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; } }
FairSync 判断是否有线程等待,若是没有则尝试获取锁,若是有则加入到等待队列。
AQS 结构:性能
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable { private static final long serialVersionUID = 7373984972572414691L; private transient volatile AbstractQueuedSynchronizer.Node head; private transient volatile AbstractQueuedSynchronizer.Node tail; private volatile int state; static final long spinForTimeoutThreshold = 1000L; private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long stateOffset; private static final long headOffset; private static final long tailOffset; private static final long waitStatusOffset; private static final long nextOffset; protected AbstractQueuedSynchronizer() { } protected final boolean compareAndSetState(int var1, int var2) { return unsafe.compareAndSwapInt(this, stateOffset, var1, var2); } public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } }
ReentrantLock 是经过使用 AQS 类来实现的,ReentrantLock 调用 lock 方法时,调用 AQS 的 acquire 方法,acquire 方法则调用子类 tryAcquire 方法,子类 tryAcquire 方法则分别有个 NonFairSync 和 FairSync 实现,若是获取失败则加入到等待队列中去。ReentrantLock 调用 unlock 方法时,调用 AQS 的 release 方法,release 方法则调用子类 tryRelease 方法,子类 release 成功后,则唤醒等待队列的第一个线程。ui