一、先整体了解一下重入锁ReentrantLock的大体思路?

先通过一张图,了解一下ReentrantLock的关系网(就好比看一个人NB不NB得先看他周围的人和家里的亲戚够不够NB,现在就开始看看ReentrantLock这个“家伙”有多牛逼!),先上图

  1. 首先ReentrantLock继承了他爸爸的AbstractQueuedSynchronizer的财产,这个人物有什么来历请看上一篇博客AbstractQueuedSynchronizer的原理实现
  2. 然后ReentrantLock还实现了他妈妈的一个目标(这里他爸爸和他妈妈本身没有太大的血缘关系)也就是ReentrantLock他实现的这个Lock接口和ReentrantLock继承的AbstractQueuedSynchronizer这个类本身没有太大关系,但是这都是他自己继承的财产他都可以随便用
  3. 而且ReentrantLock这个人自己手下还有几个子公司(也就是内部类),有一个母公司和两个子公司(这里指的是公平锁和非公平锁的两个字公司)Sync实现了AbstractQueuedSynchronizer的tryRelease方法。NonfairSync和FairSync两个类继承自Sync,实现了lock方法,然后分别公平抢占和非公平抢占针对tryAcquire有不同的实现。

二、开始梳理ReentrantLock具体实现的逻辑步骤

先看一下ReentrantLock类里面都有什么东西

二(1)重入锁中的公平锁的实现:

(1)首先公平锁对应的逻辑是 ReentrantLock 内部静态类 FairSync,看那一下静态内部类里面有什么

(2)会先从lock方法中去获取锁

final void lock() {// 调用 AQS acquire 获取锁acquire(1);
}

(3)这个acquire();方法是AQS中的方法,因为ReentrantLock继承的是AbstractQueuedSynchronizer.class这个类,而且FairSync这个又是ReentrantLock的内部类,所以就直接可以调用acquire()这个方法,(abstract static class Sync extends AbstractQueuedSynchronizer , ReentrantLock.FairSync.java重入锁中的内部类公平锁又是继承Sync 这个类(Sync .java是ReentrantLock.java中的内部类))

 /*** 这个方法也就是lock()方法的关键方法。tryAcquire获得资源,返回true,直接结束。若未获取资源,新建一个节点插入队尾,** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquire} but is otherwise uninterpreted and*        can represent anything you like.*/public final void acquire(int arg) {if (!tryAcquire(arg) &&//获取资源立刻结束acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//没有被中断过,也结束selfInterrupt();}

(4)然后是调用FairSync(公平锁中的)tryAcquire(arg)方法,去尝试再次去获取锁

1、解释这个方法是干嘛的hasQueuedPredecessors():

  • 这个方法目的就是是判断是否有其他线程比当前线程在同步队列中等待的时间更长。有的话,返回 true,否则返回 false
  • 具体解释就是:进入队列中会有一个队列可能会有多个正在等待的获取锁的线程节点,可能有Head(头结点)、Node1、Node2、Node3、Tail(尾节点),如果此时Node2节点想要去获取锁,在公平锁中他就会先去判断整个队列中是不是还有比我等待时间更长的节点,如果有,就让他先获取锁,如果没有,那我就获取锁(这里就体会到了公平性),
  • 注意:因为这个Head(头结点)、Node1、Node2、Node3、Tail(尾节点)队列是现今先出队列FIFO的队列,也就是说谁先进来的谁就在前面,也即是谁先进来的等待时间肯定都会比后进来的等待时间较长
        protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {//hasQueuedPredecessors()这个方法就是公平锁和非公平锁的不同之处之一if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {//没有前驱节点并且CAS设置成功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;}}

二(2)重入锁中的非公平锁的实现:

(1)首先非公平锁对应的逻辑是 ReentrantLock 内部静态类 NoFairSync,看那一下静态内部类里面有什么

final void lock() {/** 这里调用直接 CAS 设置 state 变量,如果设置成功,表明加锁成功。这里并没有像公平锁* 那样调用 acquire 方法让线程进入同步队列进行排队,而是直接调用 CAS 抢占锁。抢占失败* 再调用 acquire 方法将线程置于队列尾部排队。*/if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);
}

(2)也是去获取锁调用acquire()方法

public final void acquire(int arg) {//if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();
}

(3)然后再去调用tryAcquire(arg)方法,这个方法中和公平锁中的内容就会有些不一样了

protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);
}

(4)然后进入到nonfairTryAcquire()方法这里并没有调用hasQueuedPredecessors()这个方法

final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();// 获取同步状态int c = getState();// 如果同步状态 c = 0,表明锁当前没有线程获得,此时可加锁。if (c == 0) {// 调用 CAS 加锁,如果失败,则说明有其他线程在竞争获取锁if (compareAndSetState(0, acquires)) {// 设置当前线程为锁的持有线程setExclusiveOwnerThread(current);return true;}}// 如果当前线程已经持有锁,此处条件为 true,表明线程需再次获取锁,也就是重入else if (current == getExclusiveOwnerThread()) {// 计算重入后的同步状态值,acquires 一般为1int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");// 设置新的同步状态值setState(nextc);return true;}return false;
}

(五)可重入锁ReentrantLock的底层原理实现?相关推荐

  1. java中的账户冻结原理_java可重入锁(ReentrantLock)的实现原理

    前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...

  2. java多线程---重入锁ReentrantLock

    1.定义 重入锁ReentrantLock,支持重入的锁,表示一个线程对资源的重复加锁. 2.底层实现 每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获 ...

  3. 并发编程-19AQS同步组件之重入锁ReentrantLock、 读写锁ReentrantReadWriteLock、Condition

    文章目录 J.U.C脑图 ReentrantLock概述 ReentrantLock 常用方法 synchronized 和 ReentrantLock的比较 ReentrantLock示例 读写锁R ...

  4. Java 重入锁 ReentrantLock 原理分析

    1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...

  5. 重入锁ReentrantLock详解

    重入锁ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁.除此之外,该锁的还支持获取锁时的公平和非公平性选择. 在AQS实现中,当一个线程调用Mute ...

  6. java lock可重入_Java源码解析之可重入锁ReentrantLock

    本文基于jdk1.8进行分析. ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock. 首先看一下源码中对ReentrantLock的介绍. ...

  7. 重入锁-ReentrantLock

    ReentrantLock 一.重入锁的特点 1)实现重进入功能 2)分为公平锁和非公平锁: 二.ReentrantLock和AQS的关系 一.重入锁的特点 1)实现重进入功能 重进入是指任意线程获取 ...

  8. Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为"独占锁". ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychr ...

  9. Java多线程——重入锁ReentrantLock源码阅读

    上一章<AQS源码阅读>讲了AQS框架,这次讲讲它的应用类(注意不是子类实现,待会细讲). ReentrantLock,顾名思义重入锁,但什么是重入,这个锁到底是怎样的,我们来看看类的注解 ...

  10. Java 并发编程之可重入锁 ReentrantLock

    Java 提供了另外一个可重入锁,ReentrantLock,位于 java.util.concurrent.locks 包下,可以替代 synchronized,并且提供了比 synchronize ...

最新文章

  1. mysql 主从复制 和基于gtid的mysql主从复制
  2. C++STL之next_permutation使用
  3. BAT机器学习面试1000题系列(第1~10题)
  4. CGCTF-Web-签到2
  5. java12关键字var_Java 10:“ var”关键字
  6. php猴子找大王算法,教程方法;php实现猴子选大王问题算法实例电脑技巧-琪琪词资源网...
  7. 前端面试大全(问题+答案)2
  8. php base64 gzip加密,PHP base64+gzinflate压缩加密和解密算法
  9. 工作占用了太多私人时间_私人时间
  10. 如何删除后缀.Tater勒索病毒并解密.tater勒索病毒加密的病毒文件
  11. 如何用Scapy写一个端口扫描器?
  12. Shufflenet解读
  13. 离散数据编码方式总结(OneHotEncoder、LabelEncoder、OrdinalEncoder、get_dummies、DictVectorizer、to_categorical的区别?)
  14. 一战封神快速升级攻略
  15. 不当程序员,你会干什么
  16. 2020年G1工业锅炉司炉考试总结及G1工业锅炉司炉试题及答案
  17. scratch二次开发(一)
  18. html img设置形状,图片img直接设置样式
  19. multisim中轻触开关在哪_proteus中这个开关在哪
  20. JavaScript实现加密与解密详解

热门文章

  1. kd树 python实现_Python语言描述KNN算法与Kd树
  2. 孪生支持向量机基本原理
  3. 多项式插值与样条插值的解释与示例(matlab)
  4. 职场潜规则:非985院校的简历,一律扔进垃圾桶
  5. 推荐16个前端必备的实用工具与网站
  6. qlabel可以选中吗_qlabel 详解
  7. 白嫖!白嫖!【尚学堂】高淇Java300集全套学习资料!
  8. Python和R语言的区别
  9. 软件测试工程师面试自我介绍部分模板
  10. 2022百度网盘无限扩容方法技术分享