
并发编程源码分析
文章平均质量分 79
并发编程源码分析,多线程、并发控制、线程安全、性能优化
xiaolyuh123
凡是过去,皆为序幕
展开
-
多线程下嵌套异步任务导致程序假死
多线程下嵌套异步任务导致程序假死Future导致的程序假死原创 2022-04-15 18:38:22 · 2252 阅读 · 2 评论 -
LocalDateTime
package com.xiaolyuh;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;import java.time.format.DateTimeFormatter;import java.time.temporal.TemporalAdjusters;public class LocalDateTimeTest { public static void原创 2021-03-24 15:46:33 · 425 阅读 · 0 评论 -
Java中的指令重排
在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序分3种类型:编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-Level Parallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。内存系统的重排序。...原创 2019-11-28 10:57:20 · 7098 阅读 · 6 评论 -
Java内存模型
线程之间的通信和同步线程之间的通信和同步是并发编程领域的关键问题。线程之间的通信通信是指线程之间以何种机制来交换信息。线程之间的通信一般有两种方式:共享内存和消息传递。在java中典型的消息传递方式就是wait()和notify()。线程之间的同步同步是指程序用于控制不同线程之间操作发生相对顺序的机制。在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线...原创 2019-11-28 10:56:43 · 171 阅读 · 0 评论 -
线程安全的单例模式
懒汉式加方法锁public class Singleton { private static Singleton singleton = null; private Singleton() { } public static synchronized Singleton getInstance() { if (Objects.isNull(s...原创 2019-11-28 10:56:06 · 197 阅读 · 0 评论 -
并发情况如何提升同步代码块的性能
使用并发编程的目标是为了提升系统性能,引入多线程后,其实会引入额外的开销,如线程之间的协调、增加的上下文切换,线程的创建和销毁,线程的调度等等。过度或不恰当的使用,可能会导致多线程程序性能甚至比单线程还要低。影响性能的因素上下文切换是指CPU 从一个进程或线程切换到另一个进程或线程。一次上下文切换花费5000~10000个时钟周期,几微秒。在上下文切换过程中,CPU会停止处理当前运行的程序,...原创 2019-11-28 10:55:20 · 482 阅读 · 0 评论 -
并发安全
在并发的情况下使用和调度一个类,这个类总是能表现出正确的行为,那么我们就说这个类是并发安全的类。类线程安全的表现为: 操作的原子性和内存的可见性。怎么才能做到类的线程安全栈封闭所有的变量都是在方法内部声明的,这些变量都处于栈封闭状态。无状态没有任何成员变量的类,就叫无状态的类让类不可变我们常见的不可变类有:String,包装类,LoacalDateTime。让状态不可变,两种方式...原创 2019-11-28 10:28:59 · 258 阅读 · 0 评论 -
CompletionService 源码解析
CompletionService的主要作用是:按照异步任务的完成顺序,逐个获取到已经完成的异步任务。主要实现是在ExecutorCompletionService中。类图核心内部类private class QueueingFuture extends FutureTask<Void> { QueueingFuture(RunnableFuture<V> tas...原创 2019-11-28 10:12:14 · 272 阅读 · 0 评论 -
CompletableFuture 组合式异步编程
CompletableFuture是jdk1.8引入的一个新特性。 它主要是为了解决多个Future结果之间的依赖关系。比如:将两个异步计算合并为一个——这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果。等待Future集合中的所有任务都完成。仅等待Future集合中最快结束的任务完成(有可能因为它们试图通过不同的方式计算同一个值),并返回它的结果。通过编程方式完成一个Fu...原创 2019-11-28 10:11:36 · 295 阅读 · 0 评论 -
FutureTask 源码解析
Future接口和实现Future接口的FutureTask类,代表异步计算的结果。FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给 Executor执行,也可以由调用线程直接执行(FutureTask.run())。类图核心属性/** * * Possible state transitions: * NEW ->...原创 2019-11-28 10:04:12 · 341 阅读 · 0 评论 -
JAVA中常见的线程池
Executor框架最核心的类是ThreadPoolExecutor,它是线程池的实现类,详情请看ThreadPoolExecutor 源码解析。Executors还为我们提供了4种常见的线程池,他们都是基于ThreadPoolExecutor而来,还有一个是WorkStealingPool是基于ForkJoinPool的。FixedThreadPool使用方式ExecutorService...原创 2019-11-28 10:03:39 · 410 阅读 · 0 评论 -
ThreadPoolExecutor 源码解析
Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池。合理地使用线程池能够带来3个好处:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源, 还会降低系统的稳定性,使用线程池可以进行统一分...原创 2019-11-28 10:02:28 · 428 阅读 · 0 评论 -
JAVA并发容器-写时复制容器
写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以写时复制容器也是一种读写分离的思想,读和写不同的容器。如果读的时候有多个线程正在向容器添加数据,读还是会读...原创 2019-11-28 10:00:49 · 581 阅读 · 0 评论 -
JAVA并发容器-ConcurrentSkipListMap,ConcurrentSkipListSet
ConcurrentSkipListMap其实是TreeMap的并发版本。TreeMap使用的是红黑树,并且按照key的顺序排序(自然顺序、自定义顺序),但是他是非线程安全的,如果在并发环境下,建议使用ConcurrentHashMap或者ConcurrentSkipListMap。ConcurrentSkipListSet其实是TreeSet的并发版本。TreeSet底层使用红黑树,并且按照k...原创 2019-11-28 10:00:04 · 565 阅读 · 0 评论 -
JAVA并发容器-阻塞队列
在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两 种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁 (入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。非阻塞的实现方式则可以使用循环CAS的方式来实现。阻塞队列阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方......原创 2019-11-28 09:58:28 · 306 阅读 · 0 评论 -
JAVA并发容器-ConcurrentLinkedQueue 源码分析
在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两 种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁 (入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。非阻塞的实现方式则可以使用循环CAS的方式来实现。ConcurrentLinkedQueue是一个非阻塞的基于链表节点的无界线程安全队列,它遵循先进先出的原则,并采用...原创 2019-11-28 09:57:01 · 475 阅读 · 1 评论 -
JAVA并发容器-ConcurrentHashMap 1.7和1.8 源码解析
HashMap是一个线程不安全的类,在并发情况下会产生很多问题,详情可以参考HashMap 源码解析;HashTable是线程安全的类,但是它使用的是synchronized来保证线程安全,线程竞争激烈的情况下效率非常低下。在jdk1.5的时候引入了ConcurrentHashMap,这也是一个线程安全的类,它使用了分段锁的技术来提升并发访问效率。HashTable容器在竞争激烈的并发环境下表现...原创 2019-11-28 09:55:59 · 405 阅读 · 2 评论 -
二叉树遍历算法
二叉树遍历算法有4种,先序、中序、后序和层序遍历先序遍历:先根、后左、再右中序遍历:先左、后根、再右后序遍历:先左、后右、再根层序遍历:从上往下,从左往右先序遍历:A → B → D → C中序遍历:B → D → A → C后续遍历:D → B → C → A层序遍历:A → B → C → D先序遍历:A → B → D → C /** * 先序遍历递...原创 2019-11-28 09:53:51 · 436 阅读 · 0 评论 -
红黑树原理
红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。性质节点是红色或黑色。根节点是黑色。每个叶子节点(NIL)是黑色。 (注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!)每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)从任一节点到其每个叶子的所有路径都包含相...原创 2019-11-28 09:52:53 · 467 阅读 · 0 评论 -
深入分析 ThreadLocal 内存泄漏问题
转自:http://blog.xiaohansong.com/2016/08/06/ThreadLocal-memory-leak/文章目录1. 前言2. ThreadLocal 实现原理3. ThreadLocal为什么会内存泄漏 3.1. 为什么使用弱引用4. ThreadLocal 最佳实践前言ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,转载 2018-04-09 17:22:01 · 614 阅读 · 0 评论 -
HashMap 源码解析
源码学习,边看源码边加注释,边debug,边理解。基本属性常量DEFAULT_INITIAL_CAPACITY:默认数组的初始容量 - 必须是2的幂。MAXIMUM_CAPACITY:数组的最大容量DEFAULT_LOAD_FACTOR:哈希表的负载因子0.75TREEIFY_THRESHOLD:在一个桶内由树转换成链表的阈值UNTREEIFY_THRESHOLD:又树转换成链...原创 2019-11-28 09:32:30 · 192 阅读 · 0 评论 -
AQS AbstractQueuedSynchronizer 同步框架
队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架。它主要的设计思想是使用一个名为state的int类型成员变量来表示同步状态,AQS里面大部分方法都是再对这个边进行操作;再内置一个FIFO队列来完成资源获取线程的排队工作。AQS的使用方式主要使用继承方式,并且推荐使用静态内部类,这样做的好处是隔离了使用者和实现者所关注的领...原创 2019-11-27 14:43:51 · 208 阅读 · 0 评论 -
CyclicBarrier和CountDownLatch的区别
CountDownLatch是两组线程,第一组负责计数器减一,第二组是阻塞线程,当第一组线程将计数器减到0时,第二组线程才开始执行,放行是由第三方控制;CyclicBarrier是只有一组线程,只有当所有线程到达拦截点的时候,才会继续往下执行,放行是由一组线程本身控制。CountDownLatch放行条件是大于或等于线程数;CyclicBarrier放行条件是等于线程数CountDownLa...原创 2019-11-27 14:41:10 · 858 阅读 · 0 评论 -
CyclicBarrier并发工具类
作用让一 组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开放,所有被屏障拦截的线程才会继续运行。核心方法CyclicBarrier(int parties):默认构造方法,parties参数表示屏障拦截的线程数量CyclicBarrier(int parties, Runnable barrierAction):barrierAction表示屏障开放的...原创 2019-11-27 14:39:41 · 168 阅读 · 0 评论 -
CountDownLatch并发工具类
作用CountDownLatch允许一个或多个线程等待其他线程完成操作,相当于一个加强版的join方法。核心方法CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完 成,这里就传入N。countDown:负责计数器的减一await:阻塞当前线程,直到CountDownLatch计数器变成零由于countDown方法可以用在任何地方,所以这里...原创 2019-11-27 14:38:47 · 221 阅读 · 0 评论 -
Fork/Join框架运行原理
Fork/Join框架的入门可以参考Fork/Join框架。Fork/Join框架的核心类有两个一个是ForkJoinPool,它主要负责执行任务;一个是ForkJoinTask,主要负责任务的拆分和结果的合并;ForkJoinPool它和ThreadPoolExecutor一样也是一个线程池的实现,并且同样实现了Executor和ExecutorServiceie接口,类图如下:核心内部...原创 2019-11-27 14:37:58 · 402 阅读 · 0 评论 -
Fork/Join框架
Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干 个小任务(Fork),最终汇总每个小任务结果后得到大任务结果(Join)的框架。分而治之一个规模为N的问题,当N小于阀值时直接执行,当N大于阀值时将N分解成K个小规模子问题,子问题之间相互独立,并与原问题形式相同,最后将所有子问题的解合并得到原问题的解,叫做分而治之。工作窃取算法工作窃取(wo...原创 2019-11-27 14:36:51 · 1081 阅读 · 0 评论 -
java如何实现原子操作CAS
在Java中可以通过锁和循环CAS的方式来实现原子操作。使用循环CAS实现原子操作JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。CAS实现原子操作的三大问题ABA问题,循环时间长开销大,以及只能保证一个共享变量的原子操作。ABA问题因为CAS需要在操作值的时候,检查值有没有发生变化,如果没有发生变化 则更...原创 2019-11-27 14:35:53 · 453 阅读 · 0 评论 -
synchronized关键字
Java中的每一个对象都可以作为锁。具体表现为以下3种形式。对于普通同步方法,锁是当前实例对象。对于静态同步方法,锁是当前类的Class对象。对于同步方法块,锁是Synchonized括号里配置的对象。原理JVM基于进入和退出Monitor(监视器)对象来实现方法同步和代码块同步,两者的实现细节不一样。但是都可以使用monitorenter和monitorexit指令来实现。mon...原创 2019-11-27 14:35:14 · 255 阅读 · 0 评论 -
volatile关键字
volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是一个线程修改一个共享变量时,另一个线程能读到这个修改后的值。volatile的使用成本比synchronized的低,因为它不会引起上下文的切换和调度。定义为了保证共享变量被准确个一致的更新,线程因该确保通过排它锁单独获得这个变量。如果一个字段被声明成volatile,java线程内...原创 2019-11-27 14:34:23 · 179 阅读 · 0 评论 -
并发编程基础
CPU时间片轮转机制CPU时间片轮转机制也称时间片轮转法(Round-Robin,RR)主要用于分时系统中的进程调度。时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一时间段,称作它的时间片,即该进程允许运行的时间。进程之间的切换会产生上下文切花,每次切换需要耗费5000到2W个时钟周期。所有我们在进行并发编程的过程中因该尽量减少上下文的切换。怎样减少上下文的切换...原创 2019-11-27 14:33:22 · 138 阅读 · 0 评论 -
java多线程基础
java是一个天生就支持多线程的语言。查看JVM内的线程public static void main(String[] args) { //虚拟机线程管理的接口 ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); ThreadInfo[] threadInfos =...原创 2019-11-27 14:31:54 · 299 阅读 · 0 评论 -
CompletableFuture get方法一直阻塞或抛出TimeoutException
问题描述最近刚刚上线的服务突然抛出大量的TimeoutException,查询后发现是使用了CompletableFuture,并且在执行future.get(5, TimeUnit.SECONDS);时抛出了TimeoutException异常,导致接口响应很慢进而影响了其他系统的调用。问题分析首先我们知道CompletableFuture的get()方法值会阻塞主线程,直到子线程执行任务...原创 2018-12-16 01:32:26 · 20326 阅读 · 4 评论