ReentrantLock原理分析
2017-08-13 00:00
344 查看
ReentrantLock 重入锁是对 synchronized 的一种补充,ReentrantLock 提供了可定时、可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁。与 synchronized 相比, ReentrantLock 更加灵活可控,伸缩性更好。ReentrantLock 的非公平锁性能也比 synchronized 更好。
通过对 CAS 的了解,我们知道 CAS 底层也是通过排它锁实现的,只不过 CAS 是 CPU 触发的,效率更高。ReentrantLock 实现方式和 AtomicInteger 方式类似,不过 ReentrantLock 借助 AbstractQueuedSynchronizer 类来实现独占锁的功能。
ReentrantLock 主要方法如下:
ReentrantLock 构造函数,传入 boolean 参数标明是公平锁还是非公平锁,默认是非公平锁;
lock 获取锁,lock 获取锁如果成功直接返回,如果失败则阻塞等待;
lockInterruptibly 支持中断获取锁,lock 获取锁如果成功直接返回,如果失败则阻塞等待,并支持中断操作,
tryLock 获取锁,tryLock 没有设置超时时间时,获取锁成功或者失败都直接返回,tryLock 设置超时时间时,最多等待超时时间后返回结果,并支持中断操作;
unlock 释放锁,unlock 释放锁唤醒等待队列的第一个线程。
ReentrantLock 结构:
ReentrantLock 获取锁可以通过 lock 和 tryLock 获取,lock 方法获取时,如果所没被占用直接获取,如果被本线程占用,则直接获取,否则加入等待队列,并阻塞线程;tryLock 方法获取时,如果所没被占用直接获取,如果被本线程占用,也直接获取,如果被其他线程占用,则立刻返回失败。
从 ReentrantLock 中我们可以看到 ReentrantLock 的锁是通过 Sync 这个类完成的,Sync 则继承自 AbstractQueuedSynchronizer,AQS 是独占锁和共享锁的父类,通过 AQS 的 compareAndSetState 方法来进行加锁从而实现独占锁的功能。
Sync 有两个子类,分别是 FairSync 和 NonfairSync。
NonfairSync 结构:
NonfairSync 则先尝试获取锁,如果获取失败则再加入等待队列。ReentrantLock 默认是非公平锁。
FairSync 结构:
FairSync 判断是否有线程等待,如果没有则尝试获取锁,如果有则加入到等待队列。
AQS 结构:
ReentrantLock 是通过使用 AQS 类来实现的,ReentrantLock 调用 lock 方法时,调用 AQS 的 acquire 方法,acquire 方法则调用子类 tryAcquire 方法,子类 tryAcquire 方法则分别有个 NonFairSync 和 FairSync 实现,如果获取失败则加入到等待队列中去。ReentrantLock 调用 unlock 方法时,调用 AQS 的 release 方法,release 方法则调用子类 tryRelease 方法,子类 release 成功后,则唤醒等待队列的第一个线程。
通过对 CAS 的了解,我们知道 CAS 底层也是通过排它锁实现的,只不过 CAS 是 CPU 触发的,效率更高。ReentrantLock 实现方式和 AtomicInteger 方式类似,不过 ReentrantLock 借助 AbstractQueuedSynchronizer 类来实现独占锁的功能。
ReentrantLock 主要方法如下:
ReentrantLock 构造函数,传入 boolean 参数标明是公平锁还是非公平锁,默认是非公平锁;
lock 获取锁,lock 获取锁如果成功直接返回,如果失败则阻塞等待;
lockInterruptibly 支持中断获取锁,lock 获取锁如果成功直接返回,如果失败则阻塞等待,并支持中断操作,
tryLock 获取锁,tryLock 没有设置超时时间时,获取锁成功或者失败都直接返回,tryLock 设置超时时间时,最多等待超时时间后返回结果,并支持中断操作;
unlock 释放锁,unlock 释放锁唤醒等待队列的第一个线程。
ReentrantLock 结构:
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 结构:
/** * 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 成功后,则唤醒等待队列的第一个线程。
相关文章推荐
- Java多线程编程-(12)-Java中的队列同步器AQS和ReentrantLock锁原理简要分析
- Java多线程编程-(14)-Java中的队列同步器AQS和ReentrantLock锁原理简要分析
- Java 重入锁 ReentrantLock 原理分析
- java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析
- 分析ReentrantLock的实现原理
- ReentrantReadWriteLock原理分析
- ReentrantLock实现原理分析
- java并发锁ReentrantLock源码分析一 可重入支持中断锁的实现原理
- Java并发编程系列-ReentrantLock原理分析
- ReentrantLock实现原理分析
- ReentrantLock实现原理深入探究
- ReentrantLock实现原理深入探究
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
- Java锁(二)ReentrantLock独占锁分析
- 【Java并发编程】15、ReentrantLock实现原理深入探究
- ReentrantReadWriteLock可重入读写锁分析
- ReentrantLock实现原理
- 轻松学习java可重入锁(ReentrantLock)的实现原理
- “J.U.C”:ReentrantLock之二lock方法分析
- Lock、ReentrantLock和AbstractQueuedSynchronizer的源码要点分析整理