jdk1.8 J.U.C并发源码阅读------ReentrantLock源码解析
来源:互联网 发布:软件测试第二版pdf 编辑:程序博客网 时间:2024/06/05 17:49
一、继承关系
public class ReentrantLock implements Lock, java.io.Serializable实现了Lock接口、Serializable接口。
是一个独占锁,包含公平和非公平两种实现。
总结:
(1)继承了AQS抽象类实现了一个子类Sync,实现了抽象方法tryRelease,一个内部方法nonfairTryAcquire非公平锁的获取方式
(2)两个子类NonfairSync和FairSync,主要区别在与:公平锁即使当前锁是空闲的,也要查看CLH队列中是否还有其他线程在等待获取锁,如果有则获取失败,严格遵守“先到先得”的顺序;非公平锁调用lock时,首先就通过CAS尝试直接获取锁,失败则调用tryAcquire方法,该方法调用nonfairTryAcquire:如果当前锁是空闲的直接获取锁,忽略FIFO的顺序。
(3)lock接口的抽象方法:lock,lockInterruptibly,tryLock,tryLock(long time, TimeUnit unit),unlock()都是通过sync对象进行操作。
该类内部保存一个AQS子类sync的对象,在创建ReentrantLock对象时,就在构造方法内部创建了一个sync对象,所有操作都是通过sync对象进行的。
二、成员变量
/** Synchronizer providing all implementation mechanics */ private final Sync sync;//是AQS抽象类的一个子类//state在AQS中定义,表示当前锁被获取的次数
三、内部类
(1)Sync:继承了AbstractQueuedSynchronizer,有两个子类,是独占锁
abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; abstract void lock();//非公平的获取锁的方式,体现在:如果当前锁是空闲的,则该线程直接获取锁,忽略FIFO规则。 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread();//c锁的个数 int c = getState();//当前锁没有被其他线程占有 if (c == 0) {//当前线程直接获取锁//CAS将0修改成acquires if (compareAndSetState(0, acquires)) {//设置锁的占有者为当前线程 setExclusiveOwnerThread(current); return true; } }//否则,查看当前锁的占有者是否是当前线程,如果是当前线程则再次获取锁(可重入锁) else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded");//更新state的值 setState(nextc); return true; } return false; }//释放锁。过程:如果当前线程不是锁的拥有者,则抛出非法异常;否则,计算释放锁后state的个数,如果为0,则代表当前线程释放了所有的锁,就将当前拥有锁的线程设置为null,不为0则更新state的值。返回值代表该线程是否完全释放了该锁(state是否为0) protected final boolean tryRelease(int releases) {//计算释放了锁后的state值 int c = getState() - releases;//如果拥有锁的线程不是当前线程,则抛出非法异常IllegalMonitorStateException if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false;//如果当前线程释放了所有的锁,则锁处于空闲状态,同时通过setExclusiveOwnerThread将当前占有锁的线程设置为null if (c == 0) { free = true; setExclusiveOwnerThread(null); }//更新state的值 setState(c); return free; }//判断锁是否被当前线程独占 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(); } // 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; } /** * Reconstitutes the instance from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } }
(2)NonfairSync:继承自Sync,非公平独占锁的实现方式
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; //首先尝试通过CAS快速获取锁,获取失败则回归正常模式,通过AQS中的acquire方法获取锁 final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }//AQS中的acquire方法获取锁:首先尝试通过tryAcquire获取锁,成功则返回,失败则调用addWaiter将该线程封装成一个CLH队列的node节点加入到队列的尾部,然后调用acquireQueued方法,在队列中根据FIFO顺序获取锁。 protected final boolean tryAcquire(int acquires) {//调用了父类sync的nonfairTryAcquire方法获取锁 return nonfairTryAcquire(acquires); } }
(3)FairSync:继承自Sync,公平独占锁的实现方式
static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L;//直接调用AQS父类的aquire方法 final void lock() { acquire(1); } //和非公平锁的区别:即使当前锁是空闲的,也要查看CLH队列中是否还有其他线程在等待获取锁,如果有则获取失败,严格遵守“先到先得”的顺序 protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState();//当前锁是空闲的 if (c == 0) {//当队列中已经没有其他等待获取锁的节点,就CAS设置锁的状态state,并且设置锁的占有者为当前线程 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");//更新state的值 setState(nextc); return true; }//获取锁失败 return false; } }//AQS中的方法,判断CLH队列中是否还有除自己外等待获取锁的节点(first节点当前拥有锁)public final boolean hasQueuedPredecessors() { Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); }
四、方法
1、构造方法
sync是父类SYNC类型的,指向的对象是子类NonfairSync或者FairSync类型的//默认创建的是非公平锁public ReentrantLock() { sync = new NonfairSync(); }//指定创建锁的类型public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
2、lock接口中的方法
(1)lock
public void lock() {//直接调用sync的lock,根据具体类型是公平锁还是非公平锁来决定调用的lock类型 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)); }
(5)unlock:释放锁,调用的AQS中的release方法,具体为:调用SYNC中的tryRelease(该线程是否完全释放了锁,是则释放成功,否则失败(可能该线程是重入的拥有该锁,此次释放没有完全释放掉))方法释放锁,释放成功且该节点的waitStatus不为0,则调用unparkSuccessor唤醒后继节点
public void unlock() { sync.release(1); }
public Condition newCondition() { return sync.newCondition(); }
3、其他方法
(1)getHoldCount:当前线程拥有该锁的个数
public int getHoldCount() {//getHoldCount是SYNC类中的一个方法 return sync.getHoldCount(); }final int getHoldCount() { return isHeldExclusively() ? getState() : 0; }
public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); }
public boolean isLocked() {//isLocked:SYNC类中的方法 return sync.isLocked(); }
(4)isFair:锁是否是一个公平锁
public final boolean isFair() { return sync instanceof FairSync; }
(5)getOwner:返回当前锁的占有者线程
protected Thread getOwner() { return sync.getOwner(); }
(6)hasQueuedThreads:CLH队列中是否还有节点
public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); }
public final int getQueueLength() { return sync.getQueueLength(); }
(9)getQueuedThreads:返回当前队列中所有线程的集合
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 final int getWaitQueueLength(ConditionObject condition) {//如果该condition不是本对象拥有的,则抛出异常 if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.getWaitQueueLength(); }
protected Collection<Thread> getWaitingThreads(Condition condition) { if (condition == null) throw new NullPointerException();//如果condition不是AQS中的ConditionObject类或者子类的对象则抛出异常 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner");//返回CONDITION队列中处于CONDITION状态的线程的个数 return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); }
阅读全文
0 0
- jdk1.8 J.U.C并发源码阅读------ReentrantLock源码解析
- jdk1.8 J.U.C并发源码阅读------ReentrantReadWriteLock源码解析
- jdk1.8 J.U.C并发源码阅读------CountDownLatch源码解析
- jdk1.8 J.U.C并发源码阅读------CyclicBarrier源码解析
- jdk1.8 J.U.C并发源码阅读------AQS之独占锁的获取与释放
- jdk1.8 J.U.C并发源码阅读------AQS之共享锁的获取与释放
- jdk1.8 J.U.C并发源码阅读------AQS之conditionObject内部类分析
- 源码阅读笔记:J.U.C CLH lock
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
- 【死磕Java并发】-----J.U.C之重入锁:ReentrantLock
- Java并发编程之ReentrantLock源码解析
- J.U.C--locks--ReentrantLock
- 【JUC】JDK1.8源码分析之ReentrantLock
- JDK1.8中ReentrantLock源码分析
- ReentrantLock源码阅读心得
- Reentrantlock源码解析
- ReentrantLock源码解析
- 深度解析ReentrantLock源码
- JAVA EE监听器种类
- iOS 苹果审核指南
- 集成mybatis和hibernate的sessionFactory和sqlSessionFactory的类
- java比较难面试题(一)
- iTween基础之功能简介
- jdk1.8 J.U.C并发源码阅读------ReentrantLock源码解析
- java中的静态块
- cent os7安装anaconda和pycharm
- MySQL5.7 添加用户、删除用户与授权
- storm DRPC指南
- CSS中position属性( absolute | relative | static | fixed )详解
- HTML5性能优化(一)
- 2017/8/2java前端一
- Android 懒加载