JUC 并发类及并发相关类概览,持续补充...

  • AQS

    内部有两个队列,一个等待队列(前后节点),一个条件队列(后继节点),其实是通过链表方式实现;

    等待队列是双向链表;条件队列是单向链表;条件队列如果被唤醒,将后接到等待队列上;

    通过内部持有的 state,加以模板模式,提供了两种资源争抢模式:排他、共享;而在争抢时,又辅以公平、非公平竞争的考虑;

    排他与共享分别通过子类实现的:boolean tryAcquire(tryAcquireShared(x) >= 0 来判断获取资源是否成功,同时排他限制:state 只能被一个线程修改(一般修改为 1,CAS(0,1),可重入);而共享则支持多线程同时更改 state 值(被多个线程获取);

    获取时要考虑是否关注中断唤醒行为,对应方法名后缀:-Interruptible,关注则抛异常,不关注则清除线程的中断标记位记录,继续挂起直到获取成功,再中断线程;

    总的下来,分支考虑就是:资源类型(是否排他)-> 是否公平 -> 是否关注中断(每一个都是两个方向)

    释放资源时,排他类型需要判断是否当前线程,而共享类型不需要判断线程,只关注资源池;排他类型会唤醒等待队列的下一个节点,而共享则会通过级联方式传递信号,从 head 开始唤醒,直到资源被新唤醒的线程抢光才停止;

    线程的挂起是通过 LockSupport.park(thread),支持限时挂起;

    state 释放导致等待队列判断,进而唤醒。限时挂起必定支持中断响应;

    条件队列因为初始时是通过 new ConditionObject(),可以多次创建,所以支持多个条件队列,使用同一个对象即是同一个条件队列;被唤醒时会执行 state 的资源获取,获取不到则进入等待队列;同样支持是否中断关注;而条件队列的中断有两种情况,一种在条件队列上被中断唤醒,一种是在进入等待队列后被中断唤醒;

    AQS 主要是资源 state 的 CAS 并发及线程中断挂起,排队的控制

  • AQLS

    state 的类型为 long,扩展了并发数(未来扩展)。其他与 AQS 相同。

    long 需要关注缓存行问题。

  • ReentrantLock

    基于 AQS 实现的锁,设置 state = 1;支持公平与非公平(判断队列是否有等待线程);支持重入,state 递增;竞争时只有 state = 0 才获取锁成功,否则进入等待队列;

    支持 condition 的 await 和 signal。

  • CopyOnWriteArrayList

    与 AQS 无关,使用的 synchronized 保证同步安全;当发生添加行为时,会将原数组拷贝一份进行添加,然后更新引用;当发生指定索引添加时,会定位索引,分两步进行拷贝(索引前、索引后);适合读多写少场景;addIfAbsent 会先判断(无同步锁),然后拷贝(有同步锁),判断时会先拷贝一份快照,在更新索引时判断快照是否最新,是则直接使用,否则重新拷贝;

  • CopyOnWriteArraySet

    底层使用了 CopyOnWriteArrayList。唯一性的添加则是使用了 addIfAbsent。其他大部分方法直接调用了 CopyOnWriteArrayList 的类似方法;

  • CountDownLatch

    使用了 AQS,初始化大小即为 state,每次 countDown 都是对 state - 1,而 await 则是在判断 getState() == 0 ? 1 : -1 不通过挂起在队列中,所以有多少 state 则其会被唤醒 state 次,然后重新挂起,直到 state = 0

  • ArrayBlockingQueue

    未直接使用或继承 AQS,而是通过使用 ReentrantLock 和 Condition 来完成多线程同步与挂起;

    内部使用数组存储元素,但不会扩展,实现了环形队列存储,队列元素增加 offer 及获取 poll 都使用 lock 进行同步;

    当添加成功时,进行 notEmpty.signal() 通知,唤醒获取失败的线程(notEmpty.await())处理;

    当获取成功时,进行 notFull.signal() 通知,唤添加失败的线程(notFulll.await())处理;

    offer(E) 添加返回 true/falseadd(E) 内部调用 offer,返回 false 则抛异常;put 自实现,无法添加则阻塞;

    poll() 获取返回 E/nulltake 自实现,如果获取不到则阻塞挂起;

    任何添加或获取成功,相应的都会进行 notEmptynotFull 通知,而失败则进入相反的队列挂起;

    ArrayBlockingQueue 的并发遍历实现是通过队列延展实现的(就是一个队列,不断的翻滚);类似于环形队列

JUC 并发类概览的更多相关文章

  1. JUC源码分析-集合篇:并发类容器介绍

    JUC源码分析-集合篇:并发类容器介绍 同步类容器是 线程安全 的,如 Vector.HashTable 等容器的同步功能都是由 Collections.synchronizedMap 等工厂方法去创 ...

  2. 多线程进阶——JUC并发编程之CountDownLatch源码一探究竟

    1.学习切入点 JDK的并发包中提供了几个非常有用的并发工具类. CountDownLatch. CyclicBarrier和 Semaphore工具类提供了一种并发流程控制的手段.本文将介绍Coun ...

  3. JUC并发编程学习笔记

    JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...

  4. JUC原子操作类与乐观锁CAS

    JUC原子操作类与乐观锁CAS ​ 硬件中存在并发操作的原语,从而在硬件层面提升效率.在intel的CPU中,使用cmpxchg指令.在Java发展初期,java语言是不能够利用硬件提供的这些便利来提 ...

  5. JUC并发编程与高性能内存队列disruptor实战-上

    JUC并发实战 Synchonized与Lock 区别 Synchronized是Java的关键字,由JVM层面实现的,Lock是一个接口,有实现类,由JDK实现. Synchronized无法获取锁 ...

  6. 多线程JUC并发篇常见面试详解

    @ 目录 1.JUC 简介 2.线程和进程 3.并非与并行 4.线程的状态 5.wait/sleep的区别 6.Lock 锁(重点) 1.Lock锁 2.公平非公平: 3.ReentrantLock ...

  7. 再谈AbstractQueuedSynchronizer:基于AbstractQueuedSynchronizer的并发类实现

    公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...

  8. 再谈AbstractQueuedSynchronizer3:基于AbstractQueuedSynchronizer的并发类实现

    公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...

  9. Java 并发编程-再谈 AbstractQueuedSynchronizer 3 :基于 AbstractQueuedSynchronizer 的并发类实现

    公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...

随机推荐

  1. 一个操作 cookie 的原生方法 cookieStore

    我们平时对 cookie 的增删改查等操作,都是在操作 document.cookie,这里我们介绍一个新方法cookieStore. 1. 平时如何操作 cookie document.cookie ...

  2. 一款检测代码中TODO的eslint插件

    一款检测代码中TODO的eslint插件 前言 看了我标题进来的同学应该也知道我做的是个啥东西 没错是一个eslint插件,前端魔法师们日常所使用的工具之一 什么?你不知道eslint是干嘛的--吃鲸 ...

  3. Webpack 5 配置手册(从0开始)

    针对新手入门搭建项目,Webpack5 配置手册(从0开始) webpack安装顺序 1. `npm init -y`,初始化包管理文件 package.json 2. 新建src源代码目录 3. 新 ...

  4. Java进阶专题(二十八) Service Mesh初体验

    前言 ​ ⽬前,微服务的架构⽅式在企业中得到了极⼤的发展,主要原因是其解决了传统的单体架构中存在的问题.当单体架构拆分成微服务架构就可以⾼枕⽆忧了吗? 显然不是的.微服务架构体系中同样也存在很多的挑战 ...

  5. [状压DP]子矩阵

    子 矩 阵 子矩阵 子矩阵 题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵 如,下面左图中选取第 2 . 4 ...

  6. JS基础学习第一天

    JavaScript JavaScript负责页面中的的行为. 它是一门运行在浏览器端的脚本语言. JS的编写的位置 1.可以编写到标签的指定属性中 12 <button onclick=&qu ...

  7. OO第四单元总结 and 学期总结

    第四次单元总结 本单元架构设计总结 第一次作业:类图解析 本次作业仅仅需要实现官方的UmlInteraction接口,通过反射机制在Runner中实例化一个我们实现的类,来进行类图元素的分类解析,从而 ...

  8. 并发编程(共享模型之管程wait notify)

    本文主要讲解wait/notify的正确使用姿势.park/unpark.join()的原理.模式之生产者-消费者模式(异步).保护性暂停模式(同步).线程状态转换的流程.死锁和活锁以及如何检查死锁等 ...

  9. 在Visual Studio 中使用git——给Visual Studio安装 git插件(二)

    在Visual Studio 中使用git--什么是Git(一) 第二部分: 给Visual Studio安装 git插件 如果要使用 git 进行版本管理,其实使用 git 命令行工具就完全足够了, ...

  10. inline&register

    inline关键字: 内联只是一个请求,不代表编译器会响应:同时某些编译器会将一些函数优化成为内联函数. C++在类内定义的函数默认是内联函数,具体是否真变成内联函数还需看编译器本身. registe ...