【JAVA进阶篇教学】第十五篇:Java中AQS讲解

博主打算从0-1讲解下java进阶篇教学,今天教学第十五篇:Java中AQS讲解。

在Java并发编程中,AQS(AbstractQueuedSynchronizer)是一个重要的框架,用于实现同步器和锁的基础。它提供了一种灵活的方式来实现各种同步器,如ReentrantLock、Semaphore、CountDownLatch等。本文将深入探讨AQS的原理、实现方式以及如何使用它来构建自定义的同步器。

目录

一、前言

二、AQS的原理

三、AQS的使用


一、前言

在 Java 中,AQS(AbstractQueuedSynchronizer)是一个用于实现同步器的抽象类,它提供了一种通用的机制来管理共享资源的访问。AQS 的主要作用是通过维护一个同步队列来实现对共享资源的同步访问,避免了多线程访问共享资源时可能出现的竞态条件和死锁等问题。

二、AQS的原理

AQS是通过一个FIFO(先进先出)的队列来管理等待线程,实现对共享资源的访问控制。它的核心思想是将状态的管理委托给了子类,通过模板方法模式来实现同步器的具体逻辑。AQS内部维护了一个state变量表示同步状态,以及一个双向链表来存放等待线程。
AQS的主要实现包括两个部分:状态管理和线程阻塞与唤醒。

  • 状态管理:AQS通过getState()和setState(int newState)方法来管理同步状态,同时提供了compareAndSetState(int expect, int update)方法来实现原子更新状态。
  • 线程阻塞与唤醒:AQS通过enq(Node node)和addWaiter(Node mode)等方法将等待线程加入到等待队列中,通过release(int arg)和unparkSuccessor(Node node)等方法来唤醒等待线程。

AQS 的原理主要基于以下几个方面: 

同步队列:AQS 依赖内部的同步队列(一个 FIFO 双向队列)来完成同步状态的管理。当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程。当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。

节点:同步队列中的节点(Node)用来保存获取同步状态失败的线程引用、等待状态以及前一个节点和后一个节点。节点的属性类型与名称以及描述如下表所示:

属性类型名称描述
Threadthread获取同步状态失败的线程
intwaitStatus等待状态
Nodeprev前一个节点
Nodenext后一个节点

状态变量:AQS 使用两个原子状态变量来维护同步状态:

  • state:表示资源的状态,可以用于表示锁的占用情况或者其他同步状态。
  • exclusiveOwnerThread:表示当前占用锁的线程。 

AQS 的实现通过维护状态变量和同步队列,确保了多线程对共享资源的访问是有序的,避免了竞态条件和死锁等问题的出现。

三、AQS的使用

下面是一个简单的 AQS 使用示例,演示了如何使用 AQS 来实现一个简单的锁:

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class MyLock extends AbstractQueuedSynchronizer {

    @Override
    protected boolean tryAcquire(int arg) {
        // 判断是否可以获取锁
        if (getState() == 0) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
        }
        return false;
    }

    @Override
    protected boolean tryRelease(int arg) {
        // 判断是否可以释放锁
        if (getState() == 1 && getExclusiveOwnerThread() == Thread.currentThread()) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        return false;
    }

    public void lock() {
        acquire(1);
    }

    public void unlock() {
        release(1);
    }

    public static void main(String[] args) {
        MyLock lock = new MyLock();

        // 线程 1 获取锁
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 1 获取锁成功");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("Thread 1 释放锁成功");
            }
        }).start();

        // 线程 2 获取锁
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 2 获取锁成功");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("Thread 2 释放锁成功");
            }
        }).start();
    }
}

在上述示例中,我们创建了一个名为MyLock的类,它继承自AbstractQueuedSynchronizer。在MyLock类中,我们重写了tryAcquire和tryRelease方法,用于实现锁的获取和释放逻辑。
在main方法中,我们创建了一个MyLock对象,并启动了两个线程。每个线程在执行任务之前,都需要先获取锁,然后在任务执行完毕后释放锁。由于锁是互斥的,所以只有一个线程能够同时获取锁。
通过使用 AQS,我们可以方便地实现各种同步器,如锁、信号量、栅栏等。AQS 的优点是通用性强、效率高、扩展性好,可以满足不同场景下的同步需求。

点下关注,不会迷路! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/622530.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringSecurity6实现动态权限,rememberMe、OAuth2.0授权登录,退出登录等功能

本文章对应视频可在B站查看SpringSecurity6对应视频教程,记得三连哦,这对我很重要呢! 温馨提示:视频与文章相辅相成,结合学习效果更强哦! 系列文章链接 1、初识SpringSecurity,认识主流Java权限…

2005-2022年各省共同富裕指数数据(含原始数据+结果)

2005-2022年各省共同富裕指数数据(含原始数据结果) 1、时间:2005-2022年 2、来源:统计年鉴、各省年鉴 3、范围:31省 4、指标:年份、行政区划代码、地区、人均可支配收入_元、人均消费支出_元、恩格尔系…

ASP.NET Web Api 如何使用 Swagger 管理 API

前言 Swagger 是一个开源的框架,支持 OpenAPI 规范,可以根据 API 规范自动生成美观的、易于浏览的 API 文档页面,包括请求参数、响应示例等信息,并且,Swagger UI 提供了一个交互式的界面,可以帮助我们快速…

STK12 RPO模块学习(2)

一、Coast RPO Sequence 这个序列运行卫星直到它达到了下面三个条件之一。 1)截至时间。2)圈数到达了限制。3)其他条件,比如近地点。 默认情况下,Astrogator使用“Earth HPOP Default v10”预报器。你能够修改呈其他修改器。下…

C++之map和set 的封装

通过红黑树的学习(C之红黑树-CSDN博客)让我了解到map和set的底层如何实现,这一次我们来对map和set进行封装。 目录 1.map和set底层原理 2.map和set的定义 3.map和set的仿函数 4.map和set的插入 5.map和set的迭代器 5.1迭代器的构造 5.2…

解决Android手机无法通过蓝牙给win10 PC传送文件

(一)先配对设备,正常配对就可以 (二)打开系统设置,win搜索窗口搜索“设置” (三)搜索“蓝牙” (四)打开“蓝牙和其他设备”,点击“更多蓝牙设置”…

四款不同类型的企业防泄密软件推荐

在数字化快速发展的今天,企业数据的安全与保密显得愈发重要。防泄密软件作为一种专门的数据保护工具,已经逐渐成为企业不可或缺的安全屏障。本文将深入探讨防泄密软件对企业的意义,并介绍一些市面上主流的防泄密软件。 首先,防泄密…

【MySQL复合查询】

文章目录 一、基本的使用案例二、多表查询三、自连接四、子查询4.1单行子查询4.2多行子查询in关键字all关键字any关键字 4.3多列子查询4.4 在from子句中使用子查询 解决多表问题的本质五、合并查询1.union2.union all 一、基本的使用案例 注明:以下案例使用的均为一…

Spring-依赖查找

依赖查找 根据名称进行查找 实时查找 BeanFactory beanFactory new ClassPathXmlApplicationContext("beans.xml"); Object bean beanFactory.getBean("personHolder"); System.out.println(bean);xml如下: <bean id"person" class&qu…

【数据可视化01】matplotlib实例介绍2

目录 一、引言二、实例介绍1.箱线图2.热力图3.线条形式 一、引言 接着上一文章【数据可视化01】matplotlib实例介绍1继续介绍matplotlib的实例。 二、实例介绍 在matplotlib中&#xff0c;常用的图形类型包括&#xff1a; 箱线图&#xff08;Box plot&#xff09;&#xff1…

非预警,这3本TOP期刊,为何走到On Hold这步?

本周投稿推荐 SSCI • 2区社科类&#xff0c;3.0-4.0&#xff08;社科均可&#xff09; EI • 计算机工程类&#xff08;接收广&#xff0c;录用极快&#xff09; SCI&EI • 4区生物医学类&#xff0c;1.5-2.0&#xff08;录用率99%&#xff09; • 1区工程类&#…

如何用时尚新姿讲好中国品牌故事?

品牌建设在推动高质量发展中扮演了双重角色&#xff0c;既是高质量发展的重要“承载者”&#xff0c;也是强有力的“助推器”。5月10日-11日&#xff0c;中国时尚品牌URBAN REVIVO&#xff08;以下简称UR&#xff09;以中国品牌日为起点&#xff0c;联合天猫超级品牌日&#xf…

Spring框架深度解析:打造你的Java应用梦工厂

想要在Java企业级应用开发中大展身手&#xff1f;Spring框架的核心容器是你不可或缺的伙伴&#xff01; 文章目录 一. 引言1.1 介绍Spring框架的重要性1.2 阐述核心容器在Spring框架中的作用1.3 故事开端 二. 背景介绍2.1 描述Spring框架的发展历程2.2 概述Spring框架的主要特点…

数学老师们

小学三年级之前的数学老师&#xff0c;包括学前班给过我零分的数学老师&#xff0c;模样、姓名都不记得了。能回忆起来的最早的数学老师是四、五年级的李成娥老师。 李老师四十岁左右&#xff0c;短发&#xff0c;温和、爱笑&#xff0c;尤其是在班主任张老师的衬托下&#xf…

有必要买超声波洗眼镜机吗?力荐四款实力超群超声波清洗机

在日常生活中&#xff0c;眼镜不仅仅是我们视野的延展&#xff0c;像太阳眼镜&#xff0c;也是有着独特的作用。但是&#xff0c;在每天的使用过程中&#xff0c;眼镜片表面难免会有灰尘&#xff0c;污迹&#xff0c;甚至油渍&#xff0c;这些都会对镜片的材质产生一定的损伤&a…

宝塔面板各种疑难杂症处理命令教程

下载地址&#xff1a;宝塔面板各种疑难杂症处理命令教程 这份宝塔面板各种疑难杂症处理命令教程&#xff0c;可以解决市面上遇到的各种难题&#xff0c;建议有技术能行的下载使用&#xff0c;小白也可以下载来学习可以帮助你解决宝塔面板遇到的各种难题

网络端口占用问题的综合调研与解决方案

原创 Randy 拍码场 问题背景 去年底信息安全团队进行网络权限治理&#xff0c;要求所有应用实例使用静态IP&#xff0c;公网访问策略与静态IP绑定&#xff1b;之后实例重启时偶现“端口被占用”错误。通过分析总结应用日志&#xff0c;共有以下4种错误类型&#xff0c;实质都是…

Apple store 静安·苹果店欣赏

官网&#xff1a; https://www.apple.com/today/Apple 亚洲第一大商店&#xff1a;Apple 静安零售店现已在上海开幕 静安苹果欣赏

LVGL移植到ARM开发板(GEC6818)

源码下载&#xff1a;点击跳转 下载好三个文件后&#xff0c;将其解压缩&#xff0c;并合到一个文件夹里面—— 1、修改 Makefile 删除 -Wshift-negative-value 2、修改 main.c 3、修改 lv_drv_conf.h 在lv_drv_conf.h文件屏幕驱动文件刚好与开发板LCD驱动文件一致&#xff0c…

【操作指南】银河麒麟高级服务器操作系统内核升级——基于4.19.90-17升级

1. 升级清单 升级包及依赖包清单如下。 kernel ARM架构 kernel-core-4.19.90-23.18.v2101.ky10.aarch64.rpm kernel-modules-4.19.90-23.18.v2101.ky10.aarch64.rpm kernel-4.19.90-23.18.v2101.ky10.aarch64.rpm kernel-modules-extra-4.19.90-23.18.v2101.ky10.aarch64.r…