当前位置: 首页 > article >正文

ReentrantLock实现原理

  • ReentrantLock是基于AQS实现的可重入锁,比synchronized更灵活,可以设置超时时间,可以中断,支持公平和非公平锁两种方式。
  • 公平锁获取锁的方式:
    • 主要就是这三步

  • 第一步:tryAcquire 先尝试获得锁
    • 先获取state,情况一:如果state=0,那么说明当前没有线程占着锁,如果当前线程不需要排队,那么就可以尝试CAS修改state的状态,如果CAS修改成功,就说明抢锁成功,就把setExclusiveOwnerThread设置成当前线程。程序到这里就结束啦~
      • hasQueuedPredecessors()判定是否需要排队。官方解释,如果队列中有线程排在你前面,那你就需要排队;否则当前线程就在队列的头的位置,或者队列是空的,你就可以起CAS抢锁。保证了公平性!!!

  • 情况二:如果获得state!=0,但是被自己(当前线程占用),可以直接把state加1。程序到这里就结束啦~
  • 其他情况:都认为尝试获取锁失败。那就要走第二步。
  • 第二步:addWaiter 把当前线程当作节点,放到等待队列的尾部
  • 第三步:acquireQueued  无限循环执行排队操作,也就是阻塞线程,直到获得锁
    • 如果当前线程已经排在队列头部,就尝试获得锁。获得成功程序到这就结束啦~
    • 如果没有获得锁,就执行shouldParkAfterFailedAcquire ,如果排在当前线程前面的节点状态是signal,就返回true;如果排在前面的节点是CANCELLED,把前面等待状态是CANCELLED的全部清理掉,并把当前线程的前一节点设置成signal状态,就返回false(注意这里是无限循环,下次循环就会返回true);
      • 这里返回false的好处是当前线程不需要立刻进入等待状态,可以等其他条件变化后,再判断是否进行等待状态。其次返回false,也不需要走后面的park方法啦
    • 总之,这一步就是阻塞当前线程,排队等待,直到自己排到队首。
    • 那么问题来了,我怎么能排到队首?当一个线程释放锁的时候,它会将当前头节点的下一个等待节点设置为新的头节点,并且唤醒这个新的头节点。
  • 总结:公平锁lock的步骤简单讲就是,如果你不需要排队尝试获得锁,否则就排队阻塞直到获得锁。
  • 非公平锁
    • 非公平锁在一开始比公平锁多了一步CAS抢锁的步骤。通俗讲可以插队。


http://www.kler.cn/a/311867.html

相关文章:

  • 文件上传漏洞--理论
  • 软考:去中心化的部署有什么特点
  • 5G 现网信令参数学习(3) - RrcSetup(1)
  • AndroidStudio-文本显示
  • Kubebot:一款Google云平台下的Slackbot安全测试工具
  • SpringBoot(十三)SpringBoot配置webSocket
  • opencv anaconda yolov5安装流程
  • 【C++】C++ STL探索:Priority Queue与仿函数的深入解析
  • Leetocde146. LRU 缓存
  • 梧桐数据库(WuTongDB):postgresql 12的CBO(Cost-Based Optimizer)优化器
  • 浅谈人工智能之基于HTTP方式调用本地QWen OPenAI接口(Java版)
  • 股指期权交易详细基础介绍
  • 图像亮度均衡算法
  • QFramework v1.0 使用指南 更新篇:20240918. 新增 BindableList
  • 利用反射实现动态代理
  • qiankun沙箱实现原理
  • linux之网络命令
  • 移动开发(三):使用.NET MAUI打包第一个安卓APK完整过程
  • .NET内网实战:通过命令行解密Web.config
  • 一文了解高速工业相机
  • ant vue3 datePicker默认显示英文
  • Spring Boot中配置图片资源通常涉及到静态资源的管理
  • 基于单片机的智能家居控制系统设计
  • python 爬虫 selenium 笔记
  • HarmonyOS开发实战(5.0)实现二楼上划进入首页效果详解
  • 典型的MVC设计模式:使用JSP和JavaBean相结合的方式来动态生成网页内容典型的MVC设计模式