要深入了解java并发知识,AbstractQueuedSynchronizer(AQS)是必须要拿出来深入学习的,AQS可以说是贯穿了整个JUC并发包,例如ReentrantLock,CountDownLatch,CyclicBarrier等并发类都涉及到了AQS.接下来就对AQS的实现原理进行分析. 在开始分析之前,势必先将CLH同步队列了解一下 CLH同步队列 CLH自旋锁: CLH(Craig, Landin, and Hagersten locks): 是一个自旋锁,能确保无饥饿性,提…
[Java并发] AQS抽象队列同步器源码解析--独占锁获取过程 上一篇已经讲解了AQS独占锁的获取过程,接下来就是对AQS独占锁的释放过程进行详细的分析说明,废话不多说,直接进入正文... 锁释放入口release(int arg) 首先进行说明下,能够正常执行到release方法这里来的线程都是获取到锁的,从下面代码可以看出释放锁步骤只有两个重要的方法:tryRelease 与unparkSuccessor ,tryRelease尝试释放锁,unparkSuccessor唤醒后继节点所封装的…
Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java:kagejava)并发编程学习>系列之<CAS系列>教程的第二篇:从源码追根溯源查看CAS最底层是怎么实现的. 本文主要内容:CAS追根溯源,彻底找到CAS的根在哪里. 一:查看AtomicInteger.compareAndSet源码 通过上一篇文章学习,我们知道了AtomicIntege…
深入理解Java AIO(二)—— AIO源码解析 这篇只是个占位符,占个位置,之后再详细写(这个之后可能是永远) 所以这里只简单说一下我看了个大概的实现原理,具体的等我之后更新(可能不会更新了) 当然我讲的很烂,建议如果不是特别在意的话直接跳到下一节看Linux AIO的实现,或者自己去网上找找资料(虽然我找不到就是了). 之前也说过,Java AIO是直接使用epoll + 使用了并发包中的线程池来管理任务实现的异步,整体设计思路我个人觉得应该是采用Proactor模式. 大概就是围绕一个封…
目录 非阻塞并发队列ConcurrentLinkedQueue概述 结构组成 基本不变式 head的不变式与可变式 tail的不变式与可变式 offer操作 源码解析 图解offer操作 JDK1.6 hops设计意图 poll操作 源码解析 图解poll操作 总结 参考阅读 非阻塞并发队列ConcurrentLinkedQueue概述 我们之前花了很多时间了解学习BlockingQueue阻塞队列接口下的各种实现,也大概对阻塞队列的实现机制有了一定的了解:阻塞 + 队列嘛. 而且其中绝大部分是…
为什么要说AbstractQueuedSynchronizer呢? 因为AbstractQueuedSynchronizer是JUC并发包中锁的底层支持,AbstractQueuedSynchronizer是抽象同步队列,简称AQS,是实现同步器的基础组件,并发包中锁的实现底层就是使用AQS实现,另外大多数人可能不会直接用到AQS, 但是知道其原理对于架构设计还是很有帮助的. 首先我们看一下AQS的类图结构,如下图: 从类图的关系可以看到AQS是一个FIFO的双向队列,内部通过节点head 和…
AbstractQueuedSynchronizer 队列同步器(AQS) 队列同步器 (AQS), 是用来构建锁或其他同步组件的基础框架,它通过使用 int 变量表示同步状态,通过内置的 FIFO 的队列完成资源获取的排队工作.(摘自<Java并发编程的艺术>) 我们知道获取同步状态有独占和共享两种模式,本文先针对独占模式进行分析. 变量定义 private transient volatile Node head; head 同步队列头节点 private transient volati…
Stack简介 Stack是栈.它的特性是:先进后出(FILO, First In Last Out). java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现的,这就意味着,Stack也是通过数组实现的,而非链表.当然,我们也可以将LinkedList当作栈来使用!在“Java 集合系列06之 Vector详细介绍(源码解析)和使用示例”中,已经详细介绍过Vector的数据结构,这里就不再对Stack的数据结构进行说明了. Stack的继承关系 java…
Java并发包下锁学习第二篇队列同步器 还记得在第一篇文章中,讲到的locks包下的类结果图吗?如下图: ​ 从图中,我们可以看到AbstractQueuedSynchronizer这个类很重要(在本文中,凯哥就用AQS来代替这个类).我们先来了解这个类.对这个类了解之后,学习后面的会更容易了. 本篇是<凯哥(凯哥Java:kagejava)并发编程学习>系列之<Lock系列>教程的第一篇:<Java并发包下锁学习第二篇:队列同步器>. 本文主要内容:同步器介绍:同步器…
前言 最近结合书籍<Java并发编程艺术>一直在看AQS的源码,发现AQS核心就是:利用内置的FIFO双向队列结构来实现线程排队获取int变量的同步状态,以此奠定了很多并发包中大部分实现基础,比如ReentranLock等.今天又是周末,便来总结下最近看的消化后的内容. 主要参考资料<Java并发编程艺术>(有需要的小伙伴可以找我,我这里只有电子PDF)结合ReentranLock.AQS等源码. 博文中的流程图,结构图等都是我理解之后一步步亲自画的,如果转载,请标明谢谢! 一.同…
JUC 中 回环屏障 CyclicBarrier 的使用与分析,它也可以实现像 CountDownLatch 一样让一组线程全部到达一个状态后再全部同时执行,但是 CyclicBarrier 可以被复用.那么 CyclicBarrier 内部的实现与 CountDownLatch 有何不同那? CounDownLatch在解决多个线程同步方面相对于调用线程的 join 已经提供了不少改进,但是CountDownLatch的计数器是一次性的,也就是等到计数器变为0后,再调用CountDownLat…
JDK 中基于数组的阻塞队列 ArrayBlockingQueue 原理剖析,ArrayBlockingQueue 内部如何基于一把独占锁以及对应的两个条件变量实现出入队操作的线程安全? 首先我们先大概的浏览一下ArrayBlockingQueue 的内部构造,如下类图: 如类图所示,可以看到ArrayBlockingQueue 内部有个数组items 用来存放队列元素,putIndex变量标示入队元素的下标,takeIndex是出队的下标,count是用来统计队列元素个数, 从定义可以知道,这…
JDK 中基于链表的阻塞队列 LinkedBlockingQueue 原理剖析,LinkedBlockingQueue 内部是如何使用两个独占锁 ReentrantLock 以及对应的条件变量保证多线程先入队出队操作的线程安全?为什么不使用一把锁,使用两把为何能提高并发度? LinkedBlockingQueue的实现是使用独占锁实现的阻塞队列.首先看一下LinkedBlockingQueue 的类图结构,如下图所示: 如类图所示:LinkedBlockingQueue是使用单向链表实现,有两个…
ReentrantLock是可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞后放入该锁的AQS阻塞队列里面. 首先我们先看一下ReentrantLock的类图结构,如下图所示: 从类图可以知道,ReentrantLock最终还是使用AQS来实现,并且根据参数决定内部是公平锁还是非公平锁,默认是非公平锁. 首先我们先看ReentrantLock源码,看到其构造函数及其参数,这是决定内部是公平锁还是非公平锁,如下源码所示: public ReentrantLock() {…
JDK 并发包中 ThreadLocalRandom 类原理剖析,经常使用的随机数生成器 Random 类的原理是什么?及其局限性是什么?ThreadLocalRandom 是如何利用 ThreadLocal 的原理来解决 Random 的局限性? 我们首先看Random 类及其局限性,如下: 在 JDK7 之前包括现在,java.util.Random 应该是使用比较广泛的随机数生成工具类,另外 java.lang.Math 中的随机数生成也是使用的 java.util.Random 的实例.…
当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnblogs.com/dolphin0520/p/3932921.html 由于原文作者使用的API 是1.6 版本的,参考他的文章,做了一些修改成 jdk 1.8版本的方法,涉及到的内容比较多,可能有少许错误. API : jdk1.8.0_144 ThreadPoolExecutor类 Java中线…
FutureTask可用于异步获取执行结果或取消执行任务的场景.通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果,因此,FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果.另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTa…
timer在JDK里面,是很早的一个API了.具有延时的,并具有周期性的任务,在newScheduledThreadPool出来之前我们一般会用Timer和TimerTask来做,但是Timer存在一些缺陷,为什么这么说呢? Timer只创建唯一的线程来执行所有Timer任务.如果一个timer任务的执行很耗时,会导致其他TimerTask的时效准确性出问题.例如一个TimerTask每10秒执行一次,而另外一个TimerTask每40ms执行一次,重复出现的任务会在后来的任务完成后快速连续的被…
JDK 中无界优先级队列PriorityBlockingQueue 内部使用堆算法保证每次出队都是优先级最高的元素,元素入队时候是如何建堆的,元素出队后如何调整堆的平衡的? PriorityBlockingQueue是带优先级的无界阻塞队列,每次出队都返回优先级最好或者最低的元素,内部是平衡二叉树堆的实现. 首先看一下PriorityBlockingQueue类图结构,如下: 可以看到PriorityBlockingQueue内部有个数组queue用来存放队列元素,size用来存放队列元素个数,…
JDK 中基于链表的非阻塞无界队列 ConcurrentLinkedQueue 原理剖析,ConcurrentLinkedQueue 内部是如何使用 CAS 非阻塞算法来保证多线程下入队出队操作的线程安全? ConcurrentLinkedQueue是线程安全的无界非阻塞队列,其底层数据结构是使用单向链表实现,入队和出队操作是使用我们经常提到的CAS来保证线程安全的. 我们首先看一下ConcurrentLinkedQueue的类图结构先,好有一个内部逻辑有一个大概的印象,如下图所示: 可以清楚的…
并发包中并发List只有CopyOnWriteArrayList这一个,CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行修改操作和元素迭代操作都是在底层创建一个拷贝数组(快照)上进行的,也就是写时拷贝策略. 我们首先看一下CopyOnWriteArrayList的类图有哪些属性和方法,如下图所示: 如上,CopyOnWriteArrayList的类图,每个CopyOnWriteArrayList对象里面有一个array数组对象用来存放具体元素,Reentran…
多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作的顺序是不可预期的,多线程访问同一个共享变量特别容易出现并发问题,特别是多个线程需要对一个共享变量进行写入时候,为了保证线程安全, 一般需要使用者在访问共享变量的时候进行适当的同步,如下图所示: 可以看到同步的措施一般是加锁,这就需要使用者对锁也要有一定了解,这显然加重了使用者的负担.那么有没有一种方式当创建一个变量的时候,每个线程对其进行访问的时候访问的是自己线程的变量呢?其实ThreaLocal就可以做这…
JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的. thread和runnable不讨论了. 太多地方可以找到他们的探究了 重点看callable和future, 先上一段代码: package com.future.chenjun.test; import java.util.concurrent.Callab…
SimpleDateFormat 是 Java 提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个 SimpleDateFormat 实例对日期进行解析或者格式化会导致程序出错,本节就讨论下它为何是线程不安全的,以及如何避免. 为了复现上面所说的不安全,我们要用一个例子来突出这个不安全,例子如下: package com.hjc; import java.text.ParseException; import java.text.SimpleD…
1.ArrayList简介 ArrayList是一个数组队列,与java中的数组的容量固定不同,它可以动态的实现容量的增涨.所以ArrayList也叫动态数组.当我们知道有多少个数据元素的时候,我们用传统数组就可以解决问题,可当我们不知道有多少个数据元素的时候我们就可以用ArrayList. 2.继承关系 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess,…
目录 1.Vector介绍 2. 成员变量 3. 构造函数 4. 常用方法 4.1 增加 4.2 删除 4.3 修改 4.4 查询 4.5 其他常用函数 4.6 Lambda表达式相关的方法 4.7 如何遍历元素 5.序列化和反序列化 6.迭代器 6.1 Itr 6.2 ListItr 6.3 VectorSpliterator 7. 小结一下 1.Vector介绍 Vector和前面说的ArrayList很是类似,这里说的也是1.8版本,它是一个队列,但是本质上底层也是数组实现的.同样继承Ab…
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集合模型我们有必要弄清楚它的使用方法和它底层的实现原理.HashMap是通过key-value键值对的方式来存储数据的,通过put.get方法实现键值对的快速存取,这是HashMap最基本的用法.HashMap底层是通过数组和链表相结合的混合结构来存放数据的.我们通过分析底层源码来详细了解一下HashMap的实现原理. 1.HashMap的初始化…
AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态. AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁.它提供了三个方法(getState().setState(int newState).compareAndSetState(int expect,int update))来对同步状态state进行操作,当然AQS可以确保对state的操作是安全的. AQS通过内置的FIFO同步队列来完…
前言 Netty 的解码器有很多种,比如基于长度的,基于分割符的,私有协议的.但是,总体的思路都是一致的. 拆包思路:当数据满足了 解码条件时,将其拆开.放到数组.然后发送到业务 handler 处理. 半包思路: 当读取的数据不够时,先存起来,直到满足解码条件后,放进数组.送到业务 handler 处理. 而实现这个逻辑的就是我们今天的主角:ByteToMessageDecoder. 看名字的意思是:将字节转换成消息的解码器.人如其名.而他本身也是一个入站 handler,所以,我们还是从他的…
transient volatile native final Integer String Class &&Object newInstance Class.forName,ClassLoader.loadClass ClassLoader .getResources(), ClassLoader.getSystemResources() ClassLoader .getResources(), ClassLoader.getSystemResources() public Enumer…