Java并发源码
文章平均质量分 79
JUC包中各种并发工具的源码
A minor
本来无一物,何处惹尘埃
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
【JUC源码】JUC核心:AQS(一)底层结构分析
首先,从类注释可以得到的信息:提供了一种框架,自定义了先进先出的同步队列,让获取不到锁的线程能进入同步队列中排队;同步器有个状态字段,我们可以通过状态字段来判断能否得到锁,此时设计的关键在于依赖安全的 atomic value 来表示状态(虽然注释是这个意思,但实际上是通过把状态声明为 volatile,在锁里面修改状态值来保证线程安全的);子类可以通过给状态 CAS 赋值来决定能否拿到锁,可以定义那些状态可以获得锁,哪些状态表示获取不到锁(比如定义状态值是 0 可以获得锁,状态值是 1 就获取不到原创 2020-09-20 23:19:26 · 2921 阅读 · 3 评论 -
【JUC源码】JUC核心:AQS(二)同步队列源码分析(独占锁)
2.同步队列作用:管理多个线程的休眠与唤醒策略:可以执行的线程 = RUNNABLE状态 && tryAcquire成功独占模式(EXCLUSIVE):队首持锁,唤醒队二后tryAcquire尝试拿锁,队三及以后休眠共享模式(SHARED):相较于独占模式只唤醒队二 ,共享模式还唤醒所有mode=shared节点(多了一步)注:这里需要明确一点,独占和共享是对于加锁而言(能否多线程同时获锁),释放锁时没有独占和共享的概念状态初始化(0):入队的初始状态SIGINAL原创 2021-02-20 23:16:25 · 340 阅读 · 1 评论 -
【JUC源码】JUC核心:AQS(三)同步队列源码分析(共享锁)
AQS 系列:【JUC源码】JUC核心:AQS(一)底层结构分析【JUC源码】JUC核心:AQS(二)同步队列源码分析(独占锁)【JUC源码】JUC核心:AQS(三)同步队列源码分析(共享锁)【JUC源码】JUC核心:AQS(四)条件队列源码分析【JUC源码】JUC核心:关于AQS的几个问题1.共享-加锁共享锁和排他锁最大的不同在于:对于同一个共享资源,排他锁只能让一个线程获得acquireShared()共享模式下,尝试获得锁// 共享锁可以让多个线程获得,arg 可以被子类当.原创 2021-02-21 01:44:15 · 495 阅读 · 0 评论 -
【JUC源码】JUC核心:AQS(四)条件队列源码分析
条件队列:作用实现类似synchronized的wait与signal,实现在使用锁时对线程管理。而且由于实现了Condition,对线程的管理可以更加细化命名:条件队列中将node叫做waiter策略:要加入阻塞队列的前提是,当前线程已经拿到了锁,并处于运行状态。加入阻塞队列前要释放锁,即唤醒同步队列的队二结点拿锁运行条件队列中的所有结点都是在阻塞状态**唤醒操作实际是将一个node从条件队列,移动到同步队列尾,让它去返回同步队列去休眠。**并不是随机就唤醒(unpar原创 2021-02-20 23:16:06 · 299 阅读 · 1 评论 -
【JUC源码】JUC核心:关于AQS的几个问题
1.说说你对 AQS 的理解?答:回答的方向是由大到小,由全到细,由使用到原理。AQS 是一个锁框架,它定义了锁的实现机制,并开放出扩展的地方,让子类去实现,比如我们在 lock 的时候,AQS 开放出 state 字段,让子类可以根据 state 字段来决定是否能够获得锁,对于获取不到锁的线程 AQS 会自动进行管理,无需子类锁关心,这就是 lock 时锁的内部机制,封装的很好,又暴露出子类锁需要扩展的地方;AQS 底层是由同步队列 + 条件队列联手组成,同步队列管理着获取不到锁的线程的排队和释放原创 2020-09-21 00:08:43 · 856 阅读 · 0 评论 -
【JUC源码】锁:ReentrantLock(一)基本使用及特性方法
1.Reentrantlock 基本使用reentrantlock 用于替代 synchronized,需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍)PS:使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放public class ReentrantLock1 { ReentrantLock lock = new ReentrantLock(); void m1(){ lock.原创 2021-02-25 04:34:30 · 538 阅读 · 0 评论 -
【JUC源码】锁:ReentrantLock(二)生产者消费者问题
在讲 synchronized 时候,我们使用 synchronized 实现了生产者消费者问题,本篇我们再使用 Lock 和 Condition 来实现。【Java并发编程】synchronized(一):生产者消费者问题对比两种方式,Condition 的方式可以更加精确的指定哪些线程被唤醒public class MyContainer03<T> { // 容器 LinkedList<T> list = new LinkedList<>();原创 2021-02-25 04:42:47 · 446 阅读 · 0 评论 -
【JUC源码】锁:ReentrantLock(三)源码分析 --公平锁与非公平锁
从类注释可以得到的信息有:可重入互斥锁,和 synchronized 锁具有同样的功能语义,但更有扩展性;构造器接受 fairness 的参数,fairness 是 ture 时,保证获得锁时的顺序,false 不保证;公平锁的吞吐量较低,获得锁的公平性不能代表线程调度的公平性;tryLock() 无参方法没有遵循公平性,是非公平的(lock 和 unlock 都有公平和非公平,而 tryLock 只有公平锁,所以单独拿出来说一说)。补充一下第二点,ReentrantLock 的公平和非公平,原创 2020-09-23 01:56:25 · 2499 阅读 · 5 评论 -
【JUC源码】并发工具:CountDownLatch 源码分析&应用示例
CountDownLatch 中文有的叫做计数器,也有翻译为计数锁,其最大的作用不是为了加锁,而是通过计数达到等待的功能,主要有两种形式的等待:让一组线程在全部启动完成之后,再一起执行(先启动的线程需要阻塞等待后启动的线程,直到一组线程全部都启动完成后,再一起执行);主线程等待另外一组线程都执行完成之后,再继续执行。1.结构CountDownLatch 的核心成员变量及主要构造函数如下:public class CountDownLatch { // 从 Sync 的继承关系就可以看出,Co原创 2020-09-21 23:35:55 · 1659 阅读 · 2 评论 -
【JUC源码】并发工具:CyclicBarrier 源码分析&应用示例
栅栏屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。1.应用示例可以用于多线程计算数据,最后合并计算结果的场景。例如,用一个Excel保存了用户所有银行流水,每个Sheet保存一个账户近一年的每笔银行流原创 2021-04-16 14:01:35 · 223 阅读 · 1 评论 -
【JUC源码】并发工具:Semaphore 源码分析&应用示例
Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目。1.使用示例场景:资源访问,服务限流public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(2); for (int i = 0; i < 5; i ++) { new Thread(new Ta原创 2021-04-16 10:06:37 · 197 阅读 · 1 评论 -
【JUC源码】小结:对比三个类的 tryAcquire、tryRelease 实现
在前面的文章中,我们分别介绍了 Reentrantlock、Semaphore、CountDownLatch 等 JUC 包中的提供的锁及工具类。它们的底层实现都是通过一个内部类 Sync 直接继承 AQS,然后自己实现 tryAcquire() 和 tryRelease() 方法。1.ReentrantlockReentrantlock 提供了公平锁(FairSync)和非公平锁(NonFairSync)两种实现,我们最常用的就是非公平锁的实现(默认)注:公平锁和非公平锁是针对加锁而言的,在释放原创 2021-04-17 23:22:43 · 676 阅读 · 0 评论 -
【JUC源码】并发容器:CopyOnWriteArrayList 源码分析
1.结构CopyOnWriteArrayList 继承关系,核心成员变量及主要构造函数如下:public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { final transient ReentrantLock lock = new ReentrantLock(); // volatile 关键字修饰,可见的原创 2020-09-26 01:02:14 · 1951 阅读 · 1 评论 -
【JUC源码】并发容器:关于 CopyOnWriteArrayList 的几个问题
1.结构CopyOnWriteArrayList 继承关系,核心成员变量和主要构造函数如下:public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { final transient ReentrantLock lock = new ReentrantLock(); // volatile 关键字修饰,可见的原创 2020-09-26 23:48:35 · 1826 阅读 · 0 评论 -
【JUC源码】并发容器:ConcurrentHashMap(一)底层结构分析
我们从类注释上大概可以得到如下信息:所有的操作都是线程安全的,我们在使用时,无需再加锁;多个线程同时进行 put、remove 等操作时并不会阻塞,可以同时进行,和 HashTable 不同,HashTable 在操作时,会锁住整个 Map;迭代过程中,即使 Map 结构被修改,也不会抛 ConcurrentModificationException 异常;除了数组 + 链表 + 红黑树的基本结构外,新增了转移节点,是为了保证扩容 时的线程安全的节点;提供了很多 Stream 流式方法,比如说:原创 2020-09-26 23:10:49 · 2541 阅读 · 0 评论 -
【JUC源码】并发容器:ConcurrentHashMap(二)添加元素及树化源码分析
ConcurrentHashMap 系列:【JUC源码】并发容器:ConcurrentHashMap(一)底层结构分析【JUC源码】并发容器:ConcurrentHashMap(二)添加元素及树化源码分析【JUC源码】并发容器:ConcurrentHashMap(三)扩容源码分析【JUC源码】并发容器:ConcurrentHashMap(四)获取 value 源码分析【JUC源码】并发容器:关于 ConcurrentHashMap 的几个问题由于 concurrentHashMap 主要.原创 2021-02-22 19:49:43 · 568 阅读 · 0 评论 -
【JUC源码】并发容器:ConcurrentHashMap(三)扩容源码分析
ConcurrentHashMap 系列:【JUC源码】并发容器:ConcurrentHashMap(一)底层结构分析【JUC源码】并发容器:ConcurrentHashMap(二)添加元素及树化源码分析【JUC源码】并发容器:ConcurrentHashMap(三)扩容源码分析【JUC源码】并发容器:ConcurrentHashMap(四)获取 value 源码分析【JUC源码】并发容器:关于 ConcurrentHashMap 的几个问题1.扩容校验:addCount()当插入结束.原创 2021-02-22 19:49:53 · 427 阅读 · 0 评论 -
【JUC源码】并发容器:ConcurrentHashMap(四)获取 value 源码分析
ConcurrentHashMap 系列:【JUC源码】并发容器:ConcurrentHashMap(一)底层结构分析【JUC源码】并发容器:ConcurrentHashMap(二)添加元素及树化源码分析【JUC源码】并发容器:ConcurrentHashMap(三)扩容源码分析【JUC源码】并发容器:ConcurrentHashMap(四)获取 value 源码分析【JUC源码】并发容器:关于 ConcurrentHashMap 的几个问题get()ConcurrentHashMap.原创 2021-02-22 19:52:28 · 705 阅读 · 1 评论 -
【JUC源码】并发容器:关于 ConcurrentHashMap 的几个问题
3.几个问题3.1ConcurrentHashMap 和 HashMap 的相同点和不同点答:相同点:1. 都是数组 + 链表 +红黑树的数据结构,所以基本操作的思想相同;都实现了 Map 接口,继承了 AbstractMap 抽象类,所以两者的方法大多都是相似的,可以互相切换。不同点:1. ConcurrentHashMap 是线程安全的,在多线程环境下,无需加锁,可直接使用;数据结构上,ConcurrentHashMap 多了转移节点,主要用于保证扩容时的线程安全。3.2 Concu原创 2020-09-26 23:33:53 · 2448 阅读 · 0 评论 -
【JUC源码】阻塞队列:继承关系及接口分析
为了能更好的理解阻塞队列的源码,本篇我们拿 ArrayBlockingQueue 为例来看看阻塞队列的继承关系。下图是 ArrayBlockingQueue 的类图:1.Queue:队列的顶层接口public interface Queue<E> extends Collection<E> { // 入队 boolean add(E e); boolean offer(E e); // 出队 E remove(); E po原创 2021-02-22 20:01:03 · 505 阅读 · 0 评论 -
【JUC源码】阻塞队列:ArrayBlockingQueue 源码分析
从类注释可以得到的信息如下:有界的阻塞数组,容量一旦创建,后续大小无法修改;元素是有顺序的,按照先入先出进行排序,从队尾插入数据数据,从队头拿数据;队列满时,往队列中 put 数据会被阻塞,队列空时,往队列中拿数据也会被阻塞。1.结构ArrayBlockingQueue 的继承关系,核心成员变量及主要构造函数:public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements Blocking原创 2020-09-28 01:19:33 · 1593 阅读 · 1 评论 -
【JUC源码】阻塞队列:LinkedBlockingQueue 源码分析
1.结构LinkedBlockingQueue 继承关系,核心成员变量及主要构造函数:public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { // 链表的节点 static class Node<E> { E item;原创 2020-09-28 19:30:00 · 1275 阅读 · 3 评论 -
【JUC源码】阻塞队列:DelayQueue 源码分析
1.结构DelayQueue 继承关系,核心成员变量及主要构造函数:// 队列中的元素都要实现Delayed接口,实现后每个实体对象就有过期时间了public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E>{ // 组合PriorityQueue进行队列操作 private final PriorityQueue<E原创 2020-09-29 02:40:05 · 1966 阅读 · 2 评论 -
【JUC源码】阻塞队列:SynchronousQueue 源码分析(非公平模式)
从类注释可以得到的信息:队列不存储数据,所以没有大小,也无法迭代;插入操作的返回必须等待另一个线程完成对应数据的删除操作,反之亦然;队列由两种数据结构组成,分别是后入先出的堆栈和先入先出的队列,堆栈是非公平的,队列是公平的。1.结构SynchronousQueue 继承关系,核心成员变量及主要构造函数:public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer imp原创 2020-09-30 00:59:24 · 2680 阅读 · 0 评论 -
【JUC源码】阻塞队列:SynchronousQueue 源码分析(公平模式)
前篇:【JUC源码】阻塞队列:SynchronousQueue 源码分析(非公平模式)…在上一篇文章,我们说了基于栈(FILO)的 TransferStack 的非公平线程控制逻辑,本篇我们就来看看基于队列(FIFO)的 TransferQueue 的公平的线程控制逻辑。先来回顾一个问题,当前线程是如何把自己的数据传给阻塞线程的?为了方便说明,我们假设线程 1 往队列中 take 数据 ,被阻塞住了,变成阻塞线程 A ,然后线程 2 开始往队列中 put 数据 B,大致的流程是这样的:线程 1.原创 2021-02-23 00:22:01 · 411 阅读 · 4 评论 -
【JUC源码】阻塞队列:总结 --特性对比&应用场景举例
1 特性对比首先,放出一张队列的总体设计图:从图中我们可以看出几点:不同的队列有着不同的数据结构:ArrayBlockingQueue 是数组LinkedBlockingQueue 是链表SynchronousQueue 是 堆栈和队列相应的,不同的数据结构决定了入队和出队的姿势是不同的队列解耦了生产者和消费者,提供了生产者和消费者间关系的多种形式:比如 LinkedBlockingQueue、ArrayBlockingQueue 两种队列就把解耦了生产者和消费者比如 Syn原创 2020-09-30 18:06:01 · 2467 阅读 · 0 评论 -
【JUC源码】阻塞队列:各种阻塞队列面试题合集
1.队列相关问题1.1 说说你对队列的理解?答:对队列的理解:首先队列本身也是个容器,底层也会有不同的数据结构,比如 LinkedBlockingQueue 是底层是链表结构,所以可以维持先入先出的顺序,比如 DelayQueue 底层可以是队列或堆栈,所以可以保证先入先出,或者先入后出的顺序等等,底层的数据结构不同,也造成了操作实现不同;部分队列(比如 LinkedBlockingQueue )提供了暂时存储的功能,我们可以往队列里面放数据,同时也可以从队列里面拿数据,两者可以同时进行;队列把原创 2020-09-30 01:23:09 · 3150 阅读 · 0 评论 -
【JUC源码】线程池:ThreadPoolExecutor 万字源码深析(超详细注释)
ThreadPoolExecutor 的类注释有很多,选取关键的注释如下:ExecutorService 使用线程池中的线程执行提交的任务,线程池我们可以使用 Executors 进行配置;线程池解决两个问题:1:通过减少任务间的调度开销 (主要是通过线程池中的线程被重复使用的方式),来提高大量任务时的执行性能;2:提供了一种方式来管理线程和消费,维护基本数据统计等工作,比如统计已完成的任务数;Executors 为常用的场景设定了可直接初始化线程池的方法,比如 Executors#newCache原创 2020-10-03 21:03:28 · 26001 阅读 · 10 评论 -
【JUC源码】线程池:ThreadPoolExecutor(一)继承关系分析
在看 ThreadPoolExecutor 的源码前,我们先来看一下 ThreadPoolExecutor 的继承关系1.Executor定义 execute 方法来执行任务,入参是 Runnable,无出参public interface Executor { void execute(Runnable command);}2.ExecutorServiceExecutor 的功能太弱,ExecutorService 丰富了对任务的执行和管理的功能,主要代码如下:public i原创 2021-02-23 03:04:19 · 834 阅读 · 0 评论 -
【JUC源码】线程池:ThreadPoolExecutor(二)底层结构分析
在文章开始之前,我们先要明白为啥要有线程池这么个东西。线程是一种稀缺资源,若不加以限制,不仅会占用大量资源,还会影响系统的稳定性。而线程池可以对线程的创建与停止、线程数量等等因素加以控制,使得线程在一种可控的范围内运行,在保证系统稳定运行的同时,还使得性能调优更加方便。另外,每次请求到来时,由于线程的创建已经完成,所以可以直接执行任务,减少了每次创建线程、销毁线程的开销,提高了响应速度。OK,下面我们就进入正戏,源码…ThreadPoolExecutor 核心继承关系,成员变量及主要构造函数:publ原创 2021-02-23 03:04:32 · 605 阅读 · 0 评论 -
【JUC源码】线程池:ThreadPoolExecutor(三)Worker 设计及源码分析
Worker 设计思路照理说,线程池就是维持着许多线程,然后每个线程都可以很多任务。 但是这里注意一个问题,如果我们创建一个线程时直接传入一个具体的 Runnable,比如new Thread(new Runnable() { @Override public void run() { System.out.println("hello"); } }).start();那么,这个线原创 2021-02-23 03:04:46 · 561 阅读 · 4 评论 -
【JUC源码】线程池:ThreadPoolExecutor(四) 任务执行流程源码分析
1.execute()入口,选择执行策略,分为以下三种情况:情况一:工作线程 < 核心数 ,创建一个线程去执行任务情况二:工作线程 >= 核心数 且 任务队列未满,加入任务队列(等待核心线程来执行)线程池出现异常,删除当前任务极限情况:入队时可用线程刚好被回收,新建一个没有任务的线程情况三:任务队列已满队列已满 && 线程数 < maxSize:创建新的线程来处理任务队列已满 && 线程数 >= maxSize:使用 Reje原创 2021-02-23 03:05:14 · 514 阅读 · 1 评论 -
【JUC源码】线程池:ThreadPoolExecutor(五)提炼总结
经过前几篇对 ThreadPoolExecutor 的源码分析后,我们再对 ThreadPoolExecutor 的关键信息做一些总结:1)线程池解决两个问题:通过减少任务间的调度开销 (主要是通过线程池中的线程被重复使用的方式),来提高大量任务时的执行性能提供了一种方式来管理线程和消费,维护基本数据统计等工作,比如统计已完成的任务数;2)线程池容量相关参数:coreSize:当新任务提交时,发现运行的线程数小于 coreSize,一个新的线程将被创建,即使这时候其它工作线程是空闲的,可以原创 2021-02-23 03:05:30 · 544 阅读 · 0 评论 -
【JUC源码】线程池:创建线程池的参数设置思路&Excutors
ThreadPoolExecutor 初始化时,主要有如下几个参数:public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<原创 2020-10-04 00:49:46 · 3153 阅读 · 1 评论 -
【JUC源码】线程池:关于 ThreadPool 的几个问题
3.1 说说你对线程池的理解?答:答题思路从大到小,从全面到局部,总的可以这么说,线程池结合了锁、线程、队列等元素,在请求量较大的环境下,可以多线程的处理请求,充分的利用了系统的资源,提高了处理请求的速度,细节可以从以下几个方面阐述:ThreadPoolExecutor 类结构;ThreadPoolExecutor coreSize、maxSize 等重要属性;Worker 的重要作用;submit 的整个过程。3.2 ThreadPoolExecutor、Executor、Executor原创 2020-10-03 21:25:39 · 1865 阅读 · 0 评论
分享