首页 > 编程语言 >AQS源码剖析

AQS源码剖析

时间:2024-08-31 16:56:32浏览次数:4  
标签:node Node AQS int 剖析 获取 源码 arg 节点

AQS源码剖析

AQS就是AbstractQueuedSynchronizer抽象类,AQS其实就是JUC包下的一个基类,JUC下的很多内容都是基于AQS实现了部分功能,比如ReentrantLock,ThreadPoolExecutor,CountDownLatch,Semaphore,CyclicBarrier等等都是基于AQS实现。

首先AQS中提供了一个由volatile修饰,并且采用CAS方式修改的int类型的state变量。

其次AQS中维护了一个双向链表,有head,有tail,并且每个节点都是Node对象。

static final class Node {
	volatile Node prev;
	volatile Node next;
	volatile Thread thread;

}

内部常用方法:

// 尝试获取独占锁, 需要⼦类实现,获取成功返回true,获取失败返回false
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}

//  尝试释放独占锁, 需要⼦类实现,释放成功返回true,释放失败返回false
protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
}

// 尝试获取共享锁, 需要⼦类实现,获取成功返回 1,获取失败返回 -1
protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
}

// 尝试释放共享锁, 需要⼦类实现,释放成功返回 1,释放失败返回 -1
protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
 }

// 添加结点到链表队尾
private Node addWaiter(Node mode) {
        // ......
 }

// 如果addWaiter尝试添加队尾失败,则再次调⽤enq此⽅法⾃旋将结点加⼊队尾
private Node enq(final Node node) {
    // ...
}

// 释放锁时,该⽅法需要负责唤醒后继节点
private void unparkSuccessor(Node node) {
    // ...
}

//检测结点状态,如果可以休眠的话则设置waitStatus=SIGNAL并调⽤LockSupport.park休息;
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    // ......
}

获取锁源码:

public final void acquire(int arg) {
    // 尝试获取锁,比如第一个线程获取到锁了,直接返回,第二个线程没有获取到锁,将自己封装成node节点并添加到队列中
    if (!tryAcquire(arg) &&
    acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
    selfInterrupt();
}
private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            // 通过CAS方式向队列中追加节点
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        // 以上CAS追加如果没有成功,出现并发冲突,也就是说向链表追加节点失败,则进入enq(node)自旋重试。
        enq(node);
        return node;
    }
// 入参:node就是当前线程的node
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                // 获取前驱节点
                final Node p = node.predecessor();
                // 如果前驱节点是头结点,则再次执行tryAcquire尝试获取锁资源,
                // 说白了紧接着就是当前node节点要执行任务了,尝试获取一下锁,看看能不能获取成功
                if (p == head && tryAcquire(arg)) {
                    // 如果获取成功了,就将当前节点设置为头结点
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                // 如果当前节点不是头结点或者没有获取锁成功,那么就将当前线程挂起
                // 说白了就是你可以先歇歇了,暂时轮不到你的了。
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

释放锁:

释放锁说白了就是当前节点释放锁资源,让后继结点持有锁,执行任务。

public final boolean release(int arg) {
    // 释放锁
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            // 如果释放锁成功,则唤醒后面排队的线程
            unparkSuccessor(h);
        return true;
    }
    return false;
}
// 唤醒后面排队的线程
// 说白了就是改变指针的指向
private void unparkSuccessor(Node node) {
    /*
     * If status is negative (i.e., possibly needing signal) try
     * to clear in anticipation of signalling.  It is OK if this
     * fails or if status is changed by waiting thread.
     */
    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);

    /*
     * Thread to unpark is held in successor, which is normally
     * just the next node.  But if cancelled or apparently null,
     * traverse backwards from tail to find the actual
     * non-cancelled successor.
     */
    // 如果后续节点为null,或者后续节点状态为取消状态,从后往前找到一个有效节点进行唤醒
    // 说白了,就是如果后继结点不是一个有效节点,则会从后往前找
    Node s = node.next;
    if (s == null || s.waitStatus > 0) {
        s = null;
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
    if (s != null)
        LockSupport.unpark(s.thread);// 唤醒和挂起操作底层使用的是UNSAFE类的park()和unpark()方法。
}

标签:node,Node,AQS,int,剖析,获取,源码,arg,节点
From: https://www.cnblogs.com/dongyaotou/p/18390464

相关文章

  • 医院设备管理系统的设计与实现 毕业设计-附源码39673
    摘 要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,医院当然也不能排除在外。医院设备管理系统是以实际运用为开发背景,运用软件工程开发方法,采用SSM技术构建的一个管理系统。整个开发过程首先对软件系统进行......
  • 直播商城小程序开发指南:基于多商户商城系统源码的实现
    本篇文章,小编将以多商户商城系统源码为基础,详细介绍如何开发一款高效、稳定的直播商城小程序。 一、直播商城小程序的市场需求与发展前景直播商城小程序作为一种轻量级的应用形式,用户无需下载安装即可通过微信等社交平台直接访问,这为商家提供了更为便捷的客户触达方式。对于多商户......
  • flask 电子设备租赁大数据可视化分析平台 毕业设计-附源码22746
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对电子设备租赁大数据可视化分析平台等问题,对电子设备租赁大数据可视化分析平台进行研究分析,然......
  • 基于asp.net的小区物业管理系统附完整源码
    今天给大家分享一个小区物业管理系统,希望对大家的学习有所帮助1.主要功能该系统的主要功能包含三个角色,管理员、员工、业主,主要功能包含用户管理、车位管理、业主管理、数据库备份、个人中心、密码修改、报修管理、物业费管理、用户注册登录等等模块。2.开发工具及其......
  • 深入解析多商户商城系统源码:如何开发直播商城小程序?
    本篇文章,小编将深入解析多商户商城系统源码的关键技术,并详细探讨如何基于这些源码开发一个功能完善的直播商城小程序。一、多商户商城系统源码的核心构架多商户商城系统源码的核心在于其能够支持多个商户独立运营,但同时又在一个统一的平台上实现数据的共享与整合。这个系统的核心构......
  • (免费源码)计算机毕业设计必看必学 SSM大学生实习就业推荐系统68986 原创定制程序 java
    SSM大学生实习就业推荐系统 摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于角度存在偏差,人们经常能够获取不同类型的信息,这也是技术最为难以攻克的课题。针对大学生实习就业推荐系统等问题,对大学生实习就业推荐系统进行研究......
  • 推荐一个功能完善的高颜值后台系统,高效、灵活、易扩展,开箱即用(带私活源码)
     前言在当前的软件开发领域,后台管理系统的构建常常面临诸多挑战,如复杂的权限管理、多语言支持、响应式设计等。现有解决方案可能存在功能不丰富、定制难度大、开发效率低等问题。为了解决这些痛点,一款新的软件——DcatAdmin,应运而生,提供了一个高-效、灵活、易扩展的后台系......
  • 推荐一个开箱即用的中后台前端解决方案,基于vue3开发,私活神器(带源码)
     前言在现代软件开发中,中后台系统的开发往往面临诸多挑战,如技术选型、组件库的丰富性、开发效率等。现有的解-决方案可能存在技术栈陈旧、定制性差、study成-本高等问题。为了解决这些痛点,一款新的软件——vue-element-plus-admin,应运而生,提供了一个基于新技术栈的中后台前......
  • A-计算机毕业设计定制:10508民大校园美食推荐系统的设计与实现(免费领源码)可做计算机毕
    摘要 随着数字化时代的到来,校园美食推荐系统的设计与实现具有重要意义。针对民大校园中商家、普通用户和管理员之间的信息交互和服务需求,开发这样一个系统能够有效促进校园内美食资源的共享和利用,提供美食介绍和美食推荐的渠道,提高校园内美食行业的服务水平,增强校园内外用户......
  • A-计算机毕业设计定制:18099居家养老服务系统(免费领源码)可做计算机毕业设计JAVA、PHP
    摘  要1绪论1.1研究背景1.2研究意义1.3主要研究内容1.4论文章节安排2 相关技术介绍2.1Node.JS编程语言2.2MySQL数据库3 系统分析3.1可行性分析3.1.1技术可行性分析3.1.2经济可行性分析3.1.3操作可行性分析3.2系统流程分析3.2.1 ......