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

网站建设敬请期待图片素材wordpress 获取菜单id

网站建设敬请期待图片素材,wordpress 获取菜单id,阿里网站怎么建设,网站 建设 流行 数据库ReentrantLock源码解析 概括AQS实现构造方法lock方法公平锁执行lock方法公平锁lock流程图 非公平锁执行lock方法线程获取公平锁和非公平锁的区别 释放锁 概括 ReentrantLock,是Lock接口的实现类,我们查看其内的一些方法 我们可以发现其内大部分方法都是…

ReentrantLock源码解析

  • 概括
    • AQS实现
    • 构造方法
    • lock方法
      • 公平锁执行lock方法
        • 公平锁lock流程图
      • 非公平锁执行lock方法
        • 线程获取公平锁和非公平锁的区别
    • 释放锁


概括

ReentrantLock,是Lock接口的实现类,我们查看其内的一些方法

在这里插入图片描述
在这里插入图片描述
我们可以发现其内大部分方法都是通过sync对象来实现的,查看sync:
在这里插入图片描述
如上图,sync是一个抽象类,继承了AQS,而AQS的主要实现则是通过一个共享变量以及先进先出的队列实现,如下:

AQS实现

在这里插入图片描述
由volatile修饰的state,表示共享资源的状态,当其为0时表示资源空闲,>0时表示资源被锁定
在这里插入图片描述
而若有线程想要获取锁,就调用以上方法尝试使用CAS修改state变量,修改成功则表示成功获取锁,如果获取锁失败,线程就会被包装成结点加入先进先出的队列中,在AQS中该队列是通过双向链表实现的,如以下方法:
在这里插入图片描述

构造方法

我们已经知道大概知道了AQS的基本实现原理,而sync又继承了AQS。
查看其构造方法:

 public ReentrantLock() {sync = new NonfairSync();}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}

其包括两个构造方法,第一个构造方法不传入参数值,默认创建非公平锁,而第二个构造方法会根据传入的参数决定创建非公平锁还是公平锁,我们来看看什么是公平锁和非公平锁。
在这里插入图片描述
在这里插入图片描述
可以很清楚的看到非公平锁和公平锁都继承了Sync,并且它们存在两个相同的方法不同的具体实现。

lock方法

当调用lock方法时,会调用sync变量的lock方法,而Lock只是一个抽象类,调用时会根据不同的子类执行不同的方法
在这里插入图片描述

公平锁执行lock方法

公平锁会执行如下的方法:

    public final void acquire(int arg) {if (// 尝试获取锁。。。(1)!tryAcquire(arg) &&//如果获取锁失败将执行该方法.。。。(2)acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}

查看(1):

        protected final boolean tryAcquire(int acquires) {// 获取当前线程final Thread current = Thread.currentThread();//获取状态码stateint c = getState();//如果状态码为0表示锁是空闲的if (c == 0) {// 判断等待队列是否为nullif (!hasQueuedPredecessors() &&//如果为null线程通过CAS修改state变量compareAndSetState(0, acquires)) {//如果修改成功设置持有锁的线程返回truesetExclusiveOwnerThread(current);return true;}}// 如果当前的线程就是持有锁的线程,就表示该线程重入这个锁else if (current == getExclusiveOwnerThread()) {//修改state变量int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded")//通过CAS将state修改为重入的次数setState(nextc);return true;}return false;}}

我们进入以上代码的一些方法中查看:
该方法主要是判断队列中有没有其他要竞争锁的线程,如果存在当前线程就需要入队按照竞争锁的顺序来获取锁。

 public final boolean hasQueuedPredecessors() {Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;return//如果等待队列的头节点就是尾结点,因为头节点是当前持有锁的线程,那么此时没有其他竞争锁的线程,当前线程有资格竞争锁h != t &&((s = h.next) == null || s.thread != Thread.currentThread());}

设置当前持有锁的线程:

    protected final void setExclusiveOwnerThread(Thread thread) {exclusiveOwnerThread = thread;}

如果方法1返回true,则表明线程成功获取到了锁,如果返回false,则表示竞争锁失败,就会执行方法2,方法2中的参数调用了一个方法该方法会将当前线程包装成一个结点放到等待队列的尾部

    private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode);// Try the fast path of enq; backup to full enq on failureNode pred = tail;if (pred != null) {node.prev = pred;if (compareAndSetTail(pred, node)) {pred.next = node;return node;}}enq(node);return node;}

然后执行以下方法,该方法会根据线程访问的顺序也即等待队列的顺序竞争锁

    final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;//线程进入自旋状态for (;;) {//获取当前入队结点的前驱结点final Node p = node.predecessor();//当前驱结点为头节点时(即前驱结点当前持有了锁),当前线程才有获取锁的资格,当前线程通过CAS获取锁if (p == head && tryAcquire(arg)) {//当前线程获取锁成功后,将当前结点设置为头节点,返回falsesetHead(node);p.next = null; // help GCfailed = false;return interrupted;}//判断前驱结点的状态,如果状态为撤销,直接跳过if (shouldParkAfterFailedAcquire(p, node) &&//判断线程是否被中断parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}
//通过方法二的返回值,判断当前线程的中断位,可以响应中断static void selfInterrupt() {Thread.currentThread().interrupt();}
公平锁lock流程图

在这里插入图片描述

非公平锁执行lock方法

     final void lock() {//直接CAS修改state状态,尝试获取锁if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());else//竞争锁失败acquire(1);}

竞争锁失败后的逻辑与公平锁的逻辑差不多,只有第一个方法是不同的

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

与公平锁不同的是,其发现state为0时直接CAS修改state获取锁

        final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}

当线程获取不到锁时,会与线程竞争公平锁的逻辑相同,会包装为结点放入等待队列,锁定前驱结点,当前驱结点获取锁时才会尝试再次获取锁,而不是一直在等待队列中尝试获取锁,这样太浪费性能了。

线程获取公平锁和非公平锁的区别

线程调用lock方法获取公平锁时,当知道锁未被持有时,首先就会通过CAS修改state变量尝试获取锁,而非空锁则会判断等待队列中是否存在等待锁的线程,如果不存在会尝试获取锁。后面的逻辑两种则相同,加入等待队列,锁定前驱结点,当前驱节点持有锁时,会尝试获取锁。

至于超时获取锁的方法,大家可以看看源码,只比lock方法增加了一个超时的逻辑。

释放锁

释放锁的逻辑相当简单,用state变量减去当前线程重入锁的此时,使用CAS设置state变量即可

    public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;}protected final boolean tryRelease(int releases) {int c = getState() - releases;if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {free = true;setExclusiveOwnerThread(null);}setState(c);return free;}
http://www.dtcms.com/a/512410.html

相关文章:

  • 做网站用什么源码最好wordpress建站优势
  • 网站图标 代码微信开发网站建设程序
  • 修改 Docker 容器中 MySQL 8.0 默认编码为 utf8mb4_unicode_ci
  • C# Dictionary 线程安全指南:多线程下操作 Dictionary<string, DateTime> 的加锁策略
  • 企业im聊天软件支持什么功能,应该怎么选?
  • 【Linux系统编程】权限的概念
  • githup网站建设网站营销站点有你想
  • 差分|递归
  • 如何通过纺织服装MES系统提升生产效率和管理水平?
  • 打通智慧高速核心系统:湖南某新建项目的收费、通信、监控一体化实践
  • 河南网站建设优化技术福建省建设干部网站
  • 智能机器人:今年双十一“减人增效”的AI智能客服机器人方案
  • 市环保局网站建设方案建站公司哪家好 知道万维科技
  • 房产中介网站建设的目的cms 美容网站 模版
  • vue开发中,如果出现了反显数据有问题(后端明明返回的有数据,但就是不反显,没有值)是什么原因
  • 【2025-系统规划与管理师】第12章:信息系统服务管理
  • C++---嵌套类型(Nested Types)封装与泛型的基石
  • Floyd判圈算法(Floyd Cycle Detection Algorithm)
  • 网站建设支付宝温州建设学校网站
  • 深圳网站制作 优选灵点网络前端开发语言有哪些
  • .NET8 通过自定义类映射appsettings.json 文件某个节点的配置
  • 25-DAPO: An Open-Source LLM Reinforcement LearningSystem at Scale
  • 6个网站建设网站设置保存登录密码怎么取消
  • 网站建设和维护的职责网站开发工程师有证书考试吗
  • 网站建设计算机人员招聘策划营销方案
  • 《i.MX6ULL LED 驱动实战:内核模块开发与 GPIO 控制》
  • Effective Java学习笔记:用静态工厂方法代替构造器(第一条)
  • TDengine 数学函数 POW 用户手册
  • AI大模型“战国策”:主流LLM平台简单介绍
  • Prometheus监控部署——pushgateway自动推送