ArrayList源码分析--jdk1.8
LinkedList源码分析--jdk1.8
HashMap源码分析--jdk1.8
AQS源码分析--jdk1.8
ReentrantLock源码分析--jdk1.81. ReentrantLock是独占锁。
2. ReentrantLock分为公平模式和非公平模式。
3. ReentrantLock锁可重入(重新插入)
/** * @since 1.5 * @author Doug Lea * 独占锁 --默认使用非公平锁模式 * 可重入 */ public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; private final Sync sync; /** * Sync内部类,继承AQS,实现独占锁模式,作为基础内部类 */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** * 加锁 */ abstract void lock(); /** * 判断 reentranLock 状态 是否被锁住(state ?= 0) * <p>如果没被锁住尝试 原子性上锁 失败返回false</> * <p>如果被锁住 判断是否是当前线程持有锁(重入锁的实现) 如果是 state + 1 * (信号量 记录该线程持有锁的次数。 该线程每次释放所 信号量 -1。 信号量为零 代表 锁被真正释放)</> * <p>else 返回false</p> */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); //获取到当前的线程 int c = getState(); //获取锁的状态 if (c == 0) { //目前没有人在占有锁 如果锁已被经释放 再次尝试获取锁 if (compareAndSetState(0, acquires)) { //直接尝试把当前只设置成1,如果成功,把owner设置自己,并且退出 setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { // 如果当前线程为锁的拥有者 int nextc = c + acquires; //这里就是重入锁的概念,如果还是自己,则进行加1操作,因为释放和获取一定要是对等的 if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); // 累加 state 的值 此段代码 实现了重入锁 return true; } return false; //当前锁被其他线程占用,退出。 } /** * 释放锁,默认releases传1 */ protected final boolean tryRelease(int releases) { int c = getState() - releases; //获取当前的锁的状态并且减1,因为要释放锁 if (Thread.currentThread() != getExclusiveOwnerThread()) //如果当前自己不是锁的持有者,只有自己才能释放锁 throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { //释放成功 free = true; setExclusiveOwnerThread(null); } setState(c); //重新设置成状态 return free; } /** * 如果当前线程独占着锁,返回true */ protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don't need to do so to check if current thread is owner return getExclusiveOwnerThread() == Thread.currentThread(); } /** * 条件队列 */ final ConditionObject newCondition() { return new ConditionObject(); } /** * 返回锁的拥有者的线程 * 当前状态为0返回null,说明在等待中 * 当前状态不为0返回当前线程 */ final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } /** * 当前线程占着锁返回 state,否则返回0 */ final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } /** * state状态不为0标识上锁,为0表示在等待,不上锁 */ final boolean isLocked() { return getState() != 0; } /** * 反序列化 */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } /** * 构造方法,默认选择非公平锁 */ public ReentrantLock() { sync = new NonfairSync(); } /** * 构造方法,true公平锁,false非公平锁 */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
ReentrantLock implements Lock
Sync extends AbstractQueuedSynchronizer
1.ReentrantLock实现Lock接口,Lock接口定义了加锁、条件队列、解锁、加锁(中断异常)
2.Sync继承AQS抽象类,实现了独占锁,作为基础内部类
/** * 公平锁 */ 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; } }
/** * 非公平锁的同步对象 */ 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); //尝试以独占模式获取锁,如果失败加入node节点到队列中 } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } /** * 是否有等待线程 */ public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } /** * 是否有等待线程 */ public final boolean hasQueuedThreads() { return head != tail; }
1)ReentrantLock是可重入的公平/非公平模式的独占锁。 2)ReentrantLock公平锁往往没有非公平锁的效率高,但是,并不是任何场景都是以TPS作为唯一指标,公平锁 能够减少“饥饿”发生的概率,等待越久的请求越能够得到优先满足。