浅析AQS

1、AbstractQueue抽象队列、BlockingQueue阻塞队列、Deque双端队列

2、Queue FIFO先进先出,

写入:队列满阻塞等待,取出:队列满阻塞等待生产

3、使用场景:多线程并发处理、线程池

4、 阻塞队列(BlockingQueue)——四组API(添加、移除、判断队列首部的场景)

==1、会抛出异常

==2、有返回值,不抛出异常

==3、阻塞等待(一直阻塞等待)

==4、超时等待

=========抛出异常 add()\remove()\element()=========

undefined

=========有返回值,不抛出异常 add()\remove()\element()=========

undefined

=========阻塞等待(一直阻塞等待) add()\remove()\element()=========

undefined

=========超时等待 add()\remove()\element()=========

undefined

5、 同步队列

==没有容量(即不长时间存储元素)

进去一个元素,必须等待取出(take())后才能再往里边继续添加(put())

==例子:

    BlockingQueue<String> blockingQueue = new SynchronousQueue<String>();

AQS

1、一个用来构建锁和同步器的框架,定义了锁的实现机制,并开放出扩展的地方,让子类去实现。(封装得很好,但又有子类扩展的地方)

例如:lock(加锁)时锁的内部机制:

使用锁Lock时,AQS开放state字段,然子类可以根据state字段来决定是否能够获得锁,对于获取不到锁的线程,AQS会自动进行管理,无需子类锁关心。

2、使用AQS能够简单且高效地构造出大量应用广泛的同步器:ReentrantLock,Semaphore,ReentrantReadWriteLock,SynchronousQueue,FutureTask等等,都基于AQS。也可以自定义同步器。

3、AQS底层:

==(1)由 同步队列 +条件队列 联合实现(CLH队列锁)

====一般情况下有同步队列(双向链表)组成,条件队列(单向链表)不是必须存在的,当程序中存在condition时,才会存在此列表。

====同步队列管理获取不到锁的线程的排队和释放

====条件队列是在一定场景下,对同步队列的补充(非必须的),如,获得锁的线程从空队列中拿数据(队列是空的,拿不到数据的),此时,条件队列会管理该线程,使线程阻塞。

==(2)核心思想:AQS内部维护一个CLH队列来管理。

====线程请求共享资源时,

如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效线程,并且将共享资源设置为锁定状态;

如果被请求的共享资源被占用,则需要CLH队列锁实现的机制来实现线程阻塞等待以及线程被唤醒使锁的分配:即将暂时获取不到锁的线程加入到队列中。(上边的同步队列)

==(3)CLH锁队列:

====是一个虚拟的双向队列(不存在队列实例,仅存在节点间的关联关系)

====AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个个节点(Node)实现锁的分配。

==(4)AQS中同步队列的工作流程和数据结构:(结合两图理解)

浅析AQS

====工作过程:

(1)当前线程获取同步状态失败,同步器会将当线程及等待状态等信息构成一个Node节点,加入CLH队列中,放在队尾,同步器重新设置尾节点。

(2)加入队列后,会阻塞当前线程

(3)同步状态被释放并且同步器重新设置首节点,同步器唤醒等待队列中第一个节点,让其再次获取同步状态。

====AQS使用一个int成员变量来表示同步状态,通过内置的FIFO队列来完成获取资源线程的排队工作。

====AQS使用CAS对该同步状态进行原子性操作实现对其值的修改

private volatile int state;

====状态信息通过protected类型的getState,setState,compareAndSetState进行操作

undefined

4、AQS对资源的共享方式

定义了两种资源共享方式:

==(1)Exclusive(独占):又分为公平锁和非公平锁

只有一个线程能执行,如ReentrantLock

====公平锁:按照线程在队列中的排队顺序, 先到者先拿到锁

====非公平锁:当前线程要获取锁时,无视队列内的顺序,直接去强锁,谁抢到了就是谁的。

==(2)Share(共享):

多个线程可以同时执行,如Semaphore\CyclicBarrier\ReadWriteLock\CountDownLatch

==(3)ReentrantReadWriteLock:组合两种资源共享方式的

====读锁运行多个线程同时执行对同一资源进行读操作

====写锁仅允许一个线程能执行对同一资源进行写操作

==(4)不同自定义的同步器有不同的共享资源方式,自定义同步器在实现时,只需要实现共享资源state的获取与释放方式即可。

5、AQS使用的设计模式

(1)基于模板设计模式的

(2)自定义同步器的方式:

==1、继承AbstractQueuedSynchronizer并重写指定的方法

重写方法是指对于共享资源state的获取和释放

==2、将AQS组合在自定义同步组件的实现中,并调用其模板方法

这些模板方法会调用上边继承重写的方法

====AQS提高的模板方法

protected boolean tryAcquire(int)

====除以上的方法外,AQS类中其它方法不能被重写,都为final

====例:

=======独占方式=======

ReentrantLock

(1)state初始化为0,表示未锁定状态;

(2)A线程lock()时,会调用tryAcquire()独占该锁并state+1;

(3)其它线程tryAcquire()时会失败,直到A线程unlock()到state=0,即释放,其它线程才能获取该锁。

(4)A线程释放前,A自己时可以重复获取此锁的(state++),即可重入

(5)A线程释放,一定要将state回归为state=0

=======共享方式=======

CountDownLatch,任务分为N个子线程进行执行

(1)state初始化为N(与线程数一致)

(2)N个子线程并行每执行countDown()一次,state CAS减一

(3)所有子线程都执行完成后即state=0,会unpark()主调用线程

(4)主调用线程从await()函数返回,继续后续的操作

6、AQS组件

(1)Semaphore(信号量):允许多个线程同时访问

====synchronized和ReentrantLock是一次只允许一个线程访问某个资源

(2)CountDownLatch(倒计时器):同步工具类,用来协调多个线程间的同步,通常用来控制线程等待,可以让某个线程等待直到倒计时结束,再开始执行。

(3)CyclicBarrier(循环栅栏):可以实现线程间的技术等待,功能更强大复杂。

== Cyclic(可循环使用)的Barrier(屏障):

====让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障(同步点)时,才会打开屏障,所有被拦截的线程此时才会继续执行。

====CyclicBarrier的默认构造方法:CyclicBarrier(int parties)

=======parties参数:表示屏障拦截的线程数量

=======每个线程调用await()方法告知CyclicBarrier已到达屏障,然后被阻塞。

Original: https://www.cnblogs.com/hexiayuliang666/p/16156939.html
Author: 与长安故里
Title: 浅析AQS

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/570750/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 架构到底是指什么?

    架构是顶层设计;框架是面向编程或配置的半成品;组件是从技术维度上的复用;模块是从业务维度上职责的划分;系统是相互协同可运行的实体。我们要做的东西都能抽象为一个系统,架构既可做动词也…

    Java 2023年6月5日
    068
  • Spring Security系列之极速入门与实践教程

    @ 1. Spring Security 2. 实验环境准备 3. 日志级别修改 4. 配置用户名/密码 5. 数据库方式校验 6. 不拦截静态资源 7. 自定义登录页面 8. R…

    Java 2023年5月30日
    078
  • centos使用openssl生成自签名SSL证书并配置到nginx

    检查OpenSSL 检查是否已经安装openssl: 一般在CentOS7上,openssl已经默认安装好了。 生成自签名的SSL证书和私钥 新建/etc/ssl/certs/ww…

    Java 2023年5月30日
    0146
  • 基于hashset对中文词快速查询

    下载附件”百度分词词库”, 里面大约有10w个词, 使用C语言或者Java实现单词快速查找功能(不借助第三方类库工具或者数据库), 将单词载入内存中, 建立…

    Java 2023年6月13日
    077
  • 深入理解Java:注解(Annotation)自定义注解入门

    http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html Original: https://www.cnblogs…

    Java 2023年6月6日
    091
  • Android学习笔记——Android事件机制

    基于监听事件的事件处理 事件源、事件、事件监听器 内部类实现监听器 外部类实现监听器 Activity实现监听器 Lambda表达式实现监听器 基于回调事件的事件处理 对于回调事件…

    Java 2023年6月8日
    076
  • Spring学习笔记

    原生Spring 列举一些重要的 Spring 模块? Spring Core核心模块, Spring 其他所有的功能基本都需要依赖于该类库,主要提供 IoC 依赖注入功能的支持。…

    Java 2023年6月7日
    078
  • springMVC环境搭建

    6.增加jsp和servlet的jar包 taglibs standard 1.1.2 jar javax.servlet jstl 1.2 jar javax.servlet s…

    Java 2023年5月30日
    073
  • Dubbo

    远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及”请求-响应”模式的信息交换方式。 集群容错: 提供基于接口方法的透明远…

    Java 2023年6月8日
    068
  • 一次 java.util.ConcurrentModificationException 问题的fix

    我在一次多线程读写map的时候,然后再遍历的时候也遇到了该问题。 现场代码 private ConcurrentHashMap<long, set<long>&g…

    Java 2023年5月29日
    058
  • MySQL完整版详解

    一、数据库的操作 1.创建数据库 若在可视化软件上创建数据库,参考如下图 如果要创建的数据库不存在,则创建成功 create database if not exists west…

    Java 2023年6月14日
    039
  • spring-retry使用

    Spring Retry提供了自动重新调用失败的操作的功能。这在错误可能是暂时性的(例如瞬时网络故障)的情况下很有用。Spring Retry提供对流程和基于策略的行为的声明式控制…

    Java 2023年5月30日
    094
  • 第2课第5节_Java面向对象编程_异常_P【学习笔记】

    摘要:韦东山android视频学习笔记 java的异常处理的原则如下: 1、我们先写一个没有对异常处理的程序,在进行除法运算的时候,除数是非零的话,运行时没有问题的,但是除数为零的…

    Java 2023年5月29日
    086
  • Spring(四)-声明式事务

    Spring-04 声明式事务 1、事务的定义 事务就是由 一组逻辑上紧密关联的 多个工作单元(数据库操作)而合并成一个整体,这些操作 要么都执行,要么都不执行。 2、事务的特性:…

    Java 2023年6月15日
    062
  • 单向链表的介绍和实现思路

    链表在内存中的存储 链表是以节点的方式来存储, 是链式存储 每个节点包含 data 域 和 next 域。next域用来指向下一个节点 链表的各个节点不一定是连续存储的 链表分 带…

    Java 2023年6月16日
    049
  • Nginx作为代理服务

    一、代理相关概念 1、什么是代理? 代理不直接让客户端请求源服务器,由代理服务器来代为办理。 生活中如 代理理财,代理收快递都是同一个道理。 2、代理的分类 按应用场景进行分类 正…

    Java 2023年5月30日
    074
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球