java——AQS(AbstractQueuedSynchronizer)

AQS(AbstractQueuedSynchronizer)是Java并发包(java.util.concurrent)中的一个核心组件,是构建锁和其他同步器的基础框架。以下是对AQS的详细理解:

一、AQS的基本概念

AQS,全称为AbstractQueuedSynchronizer,是一个抽象的队列式同步器。它定义了一套多线程访问共享资源的同步器框架,为Java并发同步组件提供统一的底层支持。AQS是一个为各个同步组件提供基本框架的抽象类,其内部实现了同步状态的管理和线程的排队机制。

二、AQS的核心组件

  1. 同步状态:AQS使用一个int类型的成员变量来表示同步状态。这个状态变量是线程共享的资源,通过内置的FIFO队列(先进先出队列)来完成获取资源线程的排队工作。
  2. FIFO队列:AQS的底层实现是一个双向链表,用于管理等待获取同步状态的线程。当线程无法获取同步状态时,会被加入到这个队列中等待。
  3. CLH队列锁:AQS使用CLH队列锁来实现线程的阻塞等待和唤醒机制。CLH是一个虚拟的双向队列,即不存在队列实例,仅存在节点之间的关联关系。

三、AQS的工作原理

  1. 获取同步状态:当线程尝试获取同步状态时,会调用AQS的tryAcquire方法(对于独占模式)或tryAcquireShared方法(对于共享模式)。如果成功获取到同步状态,则返回true;否则,线程会被加入到等待队列中。
  2. 释放同步状态:当线程释放同步状态时,会调用AQS的tryRelease方法(对于独占模式)或tryReleaseShared方法(对于共享模式)。这些方法会修改同步状态的值,并可能唤醒等待队列中的线程。
  3. 线程排队与唤醒:等待获取同步状态的线程会被加入到FIFO队列中,并按照队列的顺序等待。当某个线程释放同步状态时,会唤醒队列中的下一个线程来尝试获取同步状态。

四、AQS的资源共享方式

AQS支持两种资源共享方式:独占(Exclusive)和共享(Share)。

  1. 独占:只有一个线程能执行,如ReentrantLock。独占锁又可分为公平锁和非公平锁。公平锁按照线程在队列中的排队顺序来获取锁,非公平锁则允许线程无视队列顺序直接去抢锁。
  2. 共享:多个线程可同时执行,如Semaphore、CountDownLatch、CyclicBarrier等。共享锁允许多个线程同时访问共享资源。

五、AQS的应用场景

AQS广泛应用于Java并发编程中,是实现各种同步机制的基础。例如,ReentrantLock、Semaphore、CountDownLatch等同步器都是基于AQS实现的。通过扩展AQS,开发者可以实现各种复杂的同步器,以满足不同的并发编程需求。

六、AQS的优缺点

优点

  1. 提供了统一的同步器框架,简化了同步器的实现过程。
  2. 使用了FIFO队列来管理等待线程,保证了线程的公平性。
  3. 提供了灵活的资源共享方式,支持独占和共享两种模式。

缺点

  1. AQS是一个相对复杂的框架,需要开发者对其内部机制有一定的了解才能正确使用。
  2. 在某些情况下,AQS的性能可能不如一些定制的同步器。

七、AQS示例

import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;

// 自定义锁类
class MyLock implements Lock {
    // 静态内部类,继承AQS
    private static class Sync extends AbstractQueuedSynchronizer {
        // 是否处于独占模式
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        // 尝试获取锁,当状态为0时获取锁成功
        public boolean tryAcquire(int acquires) {
            assert acquires == 1; // 只允许获取1个单位的锁
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        // 尝试释放锁,将状态设置为0
        protected boolean tryRelease(int releases) {
            assert releases == 1; // 只允许释放1个单位的锁
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        // 提供条件变量
        Condition newCondition() { return new ConditionObject(); }
    }

    // 将操作代理到Sync上
    private final Sync sync = new Sync();

    // 实现Lock接口的方法
    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }

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

        Runnable task = () -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 获取锁");
                // 模拟任务执行
                LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
            } finally {
                System.out.println(Thread.currentThread().getName() + " 释放锁");
                lock.unlock();
            }
        };

        Thread t1 = new Thread(task, "Thread-1");
        Thread t2 = new Thread(task, "Thread-2");

        t1.start();
        t2.start();
    }
}
  1. MyLock类:实现Lock接口,内部包含一个静态内部类Sync,该内部类继承自AbstractQueuedSynchronizer
  2. Sync类
    • isHeldExclusively:判断当前线程是否持有锁。
    • tryAcquire:尝试获取锁,如果当前状态为0(表示锁未被持有),则通过compareAndSetState方法将状态设置为1,并设置当前线程为独占线程。
    • tryRelease:尝试释放锁,将状态设置为0,并清除独占线程。
    • newCondition:创建一个条件变量。
  3. MyLock方法:将Lock接口的方法代理到Sync对象上。
  4. main方法:创建两个线程,每个线程尝试获取和释放锁,模拟任务执行。

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

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

相关文章

数据结构day5:单向循环链表 代码作业

一、loopLink.h #ifndef __LOOPLINK_H__ #define __LOOPLINK_H__#include <stdio.h> #include <stdlib.h>typedef int DataType;typedef struct node {union{int len;DataType data;};struct node* next; }loopLink, *loopLinkPtr;//创建 loopLinkPtr create();//…

后摩尔定律时代,什么将推动计算机性能优化的发展?

在摩尔定律时代&#xff0c;每两年芯片上的晶体管数量就会翻一番&#xff0c;这一看似不可避免的趋势被称为摩尔定律&#xff0c;它极大地促进了计算机性能的提高。然而&#xff0c;硅基晶体管不可能一直小下去&#xff0c;半导体晶体管的微型化推动了计算机性能的提升&#xf…

LEAST-TO-MOST PROMPTING ENABLES COMPLEX REASONING IN LARGE LANGUAGE MODELS---正文

题目 最少到最多的提示使大型语言模型能够进行复杂的推理 论文地址&#xff1a;https://arxiv.org/abs/2205.10625 摘要 思路链提示在各种自然语言推理任务中表现出色。然而&#xff0c;它在需要解决比提示中显示的示例更难的问题的任务上表现不佳。为了克服这种由易到难的概括…

0101多级nginx代理websocket配置-nginx-web服务器

1. 前言 项目一些信息需要通过站内信主动推动给用户&#xff0c;使用websocket。web服务器选用nginx&#xff0c;但是域名是以前通过阿里云申请的&#xff0c;解析ip也是阿里云的服务器&#xff0c;甲方不希望更换域名。新的系统需要部署在内网服务器&#xff0c;简单拓扑图如…

Mysql8版本的下载安装配置,无痛使用!!!!

mysql8.x版本和msyql5.x版本zip安装的方式大同小异&#xff0c;但是在mysql8.0版本不用手动创建data数据目录&#xff0c;初始化的时候会自动安装的。而且mysql8.0版本性能官方表示比mysql 5.7的快两倍&#xff01; 可以查看文章看5.7版本的安装 MySql5.7安装、配置最新版_my…

《商业模式2.0图鉴》读书笔记(如何构建创新驱动的商业模式:打破定律与重塑价值)

文章目录 引言一、构建创新商业模式的核心原则二、创新商业模式的构建维度三、商业模式设计的实践工具与方法四、从现状到未来&#xff1a;商业模式的演进路径结论附录标题图 引言 商业模式是企业连接资源与客户的桥梁&#xff0c;是价值创造与捕获的核心框架。随着市场需求和…

【数据结构】数据结构整体大纲

数据结构用来干什么的&#xff1f;很简单&#xff0c;存数据用的。 &#xff08;这篇文章仅介绍数据结构的大纲&#xff0c;详细讲解放在后面的每一个章节中&#xff0c;逐个击破&#xff09; 那为什么不直接使用数组、集合来存储呢 ——> 如果有成千上亿条数据呢&#xff…

Flutter组件————FloatingActionButton

FloatingActionButton 是Flutter中的一个组件&#xff0c;通常用于显示一个圆形的按钮&#xff0c;它悬浮在内容之上&#xff0c;旨在吸引用户的注意力&#xff0c;并代表屏幕上的主要动作。这种按钮是Material Design的一部分&#xff0c;通常放置在页面的右下角&#xff0c;但…

python rabbitmq实现简单/持久/广播/组播/topic/rpc消息异步发送可配置Django

windows首先安装rabbitmq 点击参考安装 1、环境介绍 Python 3.10.16 其他通过pip安装的版本(Django、pika、celery这几个必须要有最好版本一致) amqp 5.3.1 asgiref 3.8.1 async-timeout 5.0.1 billiard 4.2.1 celery 5.4.0 …

【Verilog】期末复习

数字逻辑电路分为哪两类&#xff1f;它们各自的特点是什么&#xff1f; 组合逻辑电路&#xff1a;任意时刻的输出仅仅取决于该时刻的输入&#xff0c;而与电路原来的状态无关 没有记忆功能&#xff0c;只有从输入到输出的通路&#xff0c;没有从输出到输入的回路 时序逻辑电路&…

光伏电站无人机巡检都有哪些功能?

焱图慧云光伏智能巡检系统主要依托于先进的无人机技术、传感器技术、图像处理技术和智能分析技术。 一、无人机自主飞行与航迹控制 全自主飞行&#xff1a;无人机能够按照预设的飞行路线自主飞行&#xff0c;完成指定的巡检任务&#xff0c;无需人工干预&#xff0c;大大提高了…

图书馆管理系统(三)基于jquery、ajax

任务3.4 借书还书页面 任务描述 这部分主要是制作借书还书的界面&#xff0c;这里我分别制作了两个网页分别用来借书和还书。此页面&#xff0c;也是通过获取books.txt内容然后添加到表格中&#xff0c;但是借还的操作没有添加到后端中去&#xff0c;只是一个简单的前端操作。…

如何使用 WebAssembly 扩展后端应用

1. WebAssembly 简介 随着互联网的发展&#xff0c;越来越多的应用借助 Javascript 转到了 Web 端&#xff0c;但人们也发现&#xff0c;随着移动互联网的兴起&#xff0c;需要把大量的应用迁移到手机端&#xff0c;随着手端的应用逻辑越来越复杂&#xff0c;Javascript 的解析…

《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》简介

《鸿蒙HarmonyOS应用开发从入门到精通&#xff08;第2版&#xff09;》已于近日上市&#xff0c;该书由北京大学出版社出版。距离第1版上市已经过去二年半多。本文希望与读者朋友们分享下这本书里面的大致内容。 封面部分 首先是介绍封面部分。 《鸿蒙HarmonyOS应用开发从入门…

Linux -- 线程控制相关的函数

目录 pthread_create -- 创建线程 参数 返回值 代码 -- 不传 args&#xff1a; 编译时带 -lpthread 运行结果 为什么输出混杂&#xff1f; 如何证明两个线程属于同一个进程&#xff1f; 如何证明是两个执行流&#xff1f; 什么是LWP&#xff1f; 代码 -- 传 args&a…

VTK知识学习(26)- 图像基本操作(一)

1、前言 图像处理离不开一些基本的图像数据操作&#xff0c;例如获取和修改图像的基本信息、访问和修改图像像素值、图像显示、图像类型转换等。熟练掌握这些基本操作有助于使用 VTK进行图像处理应用程序的快速开发。 2、图像信息的访问与修改 1&#xff09;利用vtkIamgeData…

【WPF】把DockPanel的内容生成图像

要在WPF中将一个 DockPanel 的内容生成为图像并保存&#xff0c;可以按照与之前类似的步骤进行&#xff0c;但这次我们将专注于 DockPanel 控件而不是整个窗口。 DockPanel的使用 WPF&#xff08;Windows Presentation Foundation&#xff09;中的 DockPanel 是一种布局控件&…

【Linux】处理用户输入

一、基本介绍 1、如何传递参数 向shell脚本传递数据的最基本方法就是通过命令行参数。如下&#xff0c;这条命令会向test.sh脚本传递10和20这两个参数。 ./test.sh 10 20 2、如何读取参数 bash shell会将所有的命令行参数都指派给称作位置参数&#xff08;positional parame…

SpringBoot+Vue3实现阿里云视频点播 实现教育网站 在上面上传对应的视频,用户开会员以后才能查看视频

要使用阿里云视频点播&#xff08;VOD&#xff09;实现一个教育网站&#xff0c;其中用户需要成为会员后才能查看视频&#xff0c;这个过程包括上传视频、设置权限控制、构建前端播放页面以及确保只有付费会员可以访问视频内容。 1. 视频上传与管理 创建阿里云账号&#xff…

POI-TL插件开发-表格分组插件

POI-TL版本&#xff1a;1.12.2 改造于&#xff1a;LoopRowTableRenderPolicy 模板设计&#xff1a; 分组之前&#xff1a; 分组之后&#xff1a; 代码实现&#xff1a; public class LoopRowGroupTableRenderPolicy implements RenderPolicy {private String prefix;privat…