Java Concurrent
文章平均质量分 94
贝克街的流浪猫
公众号: 贝贝猫技术分享
展开
-
Java JUC 简介
引言本系列文章旨在介绍 Java 并发相关的知识,本文作为开篇主要介绍了 JDK 中常用的并发库(JUC)的使用方式, 后续的文章中我会自上而下地剖析了 JUC 中各个部门的实现原理,从直接下级框架 AbstractQueuedSynchronizer 也就是大家常说的 AQS,再到其中使用的 CAS, Wait,Park,最后到操作系统层面的 Mutex,Condition,希望通过这篇文章,大家能够对整个 Java 并发有一个清晰全面的认识,而且把这些内容串在一起你会发现它们本质上都是相通的。并发问原创 2021-04-07 09:36:55 · 509 阅读 · 0 评论 -
Java ThreadLocal 实现
引言前面我们已经介绍了 JDK 中常用的并发库(JUC)的使用方式, 本文我们着重介绍 JUC 中 ThreadLocal 的实现方式已经 Netty 对 ThreadLocal 的增强实现。ThreadLocal实现这里我们简单地介绍一下 ThreadLocal 的实现原理,在每个 Thread 对象中都保存了一个 ThreadLocal Map,其中 key 为 ThreadLocal 对象,Value 为 ThreadLocal 的值。这里 ThreadLocalMap 中的 Entry 使用原创 2021-04-07 09:36:49 · 216 阅读 · 1 评论 -
Java ThreadPool 实现
引言前面我们已经介绍了 JDK 中常用的并发库(JUC)的使用方式, 本文我们着重介绍 JUC 中 ThreadPool 的实现方式。ThreadPool 实现在介绍 ThreadPoolExecutor 的实现时,我们着重介绍它的 execute 函数和shutdown,shutdownNow,在介绍之前,让我们来看一看 ThreadPoolExecutor 是如何维护内部数据的。/** * The main pool control state, ctl, is an atomic inte原创 2021-04-07 09:36:43 · 189 阅读 · 0 评论 -
Java ConcurrentHashMap 实现
引言从本篇文章开始,我们将介绍 Java 并发容器的实现方式,本文会着重介绍其中的 ConcurrentHashMap 部分。ConcurrentHashMap用过 HashMap 的同学应该都知道,它不是线程安全的,在极端情况下可能会发生死循环,要想在多线程环境下使用 HashMap 一个简单的思路是加一个锁,在调用 HashMap 的函数前首先要获得该锁。但是这样做有一个问题就是效率会比较差。ConcurrentHashMap 的数据组织和 HashMap 基本相同。通过一个数组来实现 Has原创 2021-04-06 09:31:37 · 342 阅读 · 0 评论 -
Java ConcurrentLinkedQueue 实现
引言本文着重介绍 Java 并发容器中 ConcurrentLinkedQueue 的实现方式。ConcurrentLinkedQueueJava提供的线程安全的 Queue 可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是 BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现。ConcurrentLinkedQueue 使用了链表原创 2021-04-06 09:31:30 · 412 阅读 · 0 评论 -
Java ConcurrentSkipListMap 实现
引言本文目前只是简单地介绍了 Java 并发容器中 ConcurrentSkipListMap 的实现方式,后续会考虑拓展本文,从源码的角度进行详细的分析。ConcurrentSkipListMap对于一个单链表,即使链表是有序的,如果我们想要在其中查找某个数据,也只能从头到尾遍历链表,这样效率自然就会很低。而跳表是在这个单链表的基础上同时维护了多个链表,并且链表是分层的。最低层的链表维护了跳表内所有的元素,每上面一层链表都是下面一层的子集。跳表内的所有链表的元素都是排序的。查找时,可以从顶级链原创 2021-04-06 09:31:25 · 192 阅读 · 1 评论 -
Java CoryOnWriteArrayList 实现
引言本文着重介绍 Java 并发容器中 CoryOnWriteArrayList 的实现方式。CopyOnWriteArrayListCopyOnWriteArrayList 用于读场景远多于写场景的情况,它能够让读与读之间不互斥,读与写也不互斥,只有写与写之间才会互斥。它的思路也很简单,内部通过一个数组来维护数据,正常读数据时直接通过索引从数组中提取数据。/** The array, accessed only via getArray/setArray. */private transien原创 2021-04-06 09:31:18 · 367 阅读 · 1 评论 -
Java LinkedBlockingQueue 实现
引言本文着重介绍 Java 并发容器中 LinkedBlockingQueue 的实现方式。LinkedBlockingQueueLinkedBlockingQueue 底层基于单向链表实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,满足FIFO的特性,为了防止 LinkedBlockingQueue 容量迅速增,损耗大量内存。通常在创建LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于Integer. MAX_VALUE。那么什么是阻塞队列呢?我们知道队列原创 2021-04-06 09:31:12 · 274 阅读 · 1 评论 -
Java PriorityBlockingQueue 实现
引言本文着重介绍 Java 并发容器中 PriorityBlockingQueue 的实现方式。PriorityBlockingQueuePriorityBlockingQueue 是一个带排序功能的阻塞队列,因为它是一个队列,没必要保证整个队列的内部顺序,只需要保证出队时按照排序结果出即可,所以其内部使用了二分堆得形式实现,同时,PriorityBlockingQueue 也是线程安全的,内部通过一个锁来控制堆数据的维护。PriorityBlockingQueue 的堆数据都保存在如下的 queu原创 2021-04-06 09:31:06 · 186 阅读 · 0 评论 -
Java Lock
引言本文着重介绍 Java 中 Lock 的不同实现方式。锁的种类在 JUC 中,大量使用到了锁,而 Java 中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录:悲观锁与乐观锁对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和大部分Lock的实现类都是悲观锁。原创 2021-04-06 09:31:00 · 372 阅读 · 0 评论 -
Java AQS 实现——数据组织
引言从本篇文章开始,我们将介绍 Java AQS 的实现方式,本文先介绍 AQS 的内部数据是如何组织的,后面的文章中再分别介绍 AQS 的各个部门实现。AQS通过前面的介绍,大家一定看出来了,上述的各种类型的锁和一些线程控制接口(CountDownLatch 等),最终都是通过 AQS 来实现的,不同之处只在于 tryAcquire 等抽象函数如何实现。从这个角度来看,AQS(AbstractQueuedSynchronizer) 这个基类设计的真的很不错,能够包容各种同步控制方案,并提供了必须的原创 2021-04-06 09:30:53 · 165 阅读 · 1 评论 -
Java AQS 实现——排他模式
引言本文着重介绍 AQS 的排他模式的实现方式。排他模式获取资源入队操作介绍完之后,我们来看一下什么情况下需要执行入队操作,我们先从排他模式说起。下面的 acquire 是 AQS 提供的一个以排他模式获取资源的函数,我们可以看到它的执行流程是:先尝试获取资源 tryAcquire,tryAcquire 是一个抽象函数,看完前面的锁的分类部分大家应该对它比较熟悉,因为通过 AQS 实现的各类锁实际上就是通过对 tryAcquire 这类抽象函数的覆写来达到各种锁的效果的。如果尝试加锁失败,也原创 2021-04-06 09:30:47 · 203 阅读 · 0 评论 -
Java AQS 实现——共享模式
引言本文着重介绍 AQS 的共享模式的实现方式。共享模式通过 AQS 不仅能够实现排他锁,而且也能够实现共享锁,就像前面介绍过的 ReentrantReadWriteLock,其中读锁就是共享锁,这部分是通过 AQS 的共享模式实现的。注意:这里我们只是以 ReentrantReadWriteLock 作为一个例子,这并不是说要想使用 AQS 的共享模式,就一定要同时使用它的排他模式,AQS 是很灵活的,你可以只使用它的共享模式,比如 CountDownLatch,也可以只使用它的排他模式,比如 R原创 2021-04-06 09:30:41 · 376 阅读 · 0 评论 -
Java AQS 实现——Condition
引言本文着重介绍 AQS 的 Condition 实现方式。Condition介绍完 AQS 的共享模式和互斥模式后,我们来看一看 AQS 是如何实现条件等待的,即 Condition。在 AQS 中通过 ConditionObject 实现 Condition。从 ConditionObject 的核心数据中,我们会发现它内部也会维护一个 Node 的队列。public class ConditionObject implements Condition, java.io.Serializabl原创 2021-04-05 11:16:08 · 253 阅读 · 1 评论 -
Java Thread 和 Park
引言从本篇文章开始,将会是一些和 Java 多线程相关的杂谈,本篇文章主要介绍 JVM 对 JavaThread 实现,以及 Thread Park 的实现。多线程相关知识ThreadHotSpot里的Thread类对应着一个OS的Thread, JavaThread类继承自Thread, 一个JavaThread实例对应着一个Java层的Thread。所以, Java层的每一个Thread在操作系统上对应一个thread, linux上就是一个轻量级task。// thread.hppcla原创 2021-04-05 11:16:02 · 1163 阅读 · 0 评论 -
Java Yield Wait Park Sleep
引言前面我们已经介绍了 Java Thread 的实现以及用来进行线程等待的 Parker 和 ParkEvent 的实现,本篇文章中我们介绍一下 Parker 和 ParkEvent 的使用,即 Yield、Wait、Park、Sleep。Yield Wait Park Sleep和 Java 并发打交道,可能经常会有让当前线程先等一等,等待某一事件发生再继续向下执行的情况。而 Thread 的 Yield Wait Park Sleep 都能造成线程的等待,并让出 CPU 执行权,那么它们都有什么原创 2021-04-05 11:15:55 · 216 阅读 · 0 评论 -
Java Interrupt
引言本文中,我们主要介绍一下 Java 提供的 Interrupt 机制的常见使用方法,以及 Interrupt 的实现。Interrupt在 Java 中,如果我们想要操作一个线程的执行状态,可以直接调用 Thread::stop 停止它的运行,但是这样显然有些粗暴,如果线程正处于临界区进行数据修改,可能会导致数据的错乱。同样,我们也可以通过 Thread::suspend 和 Thread::resume 来暂停和恢复一个线程的运行。但是上述的这些方式,都是在比较下层的方式来控制一个线程的运行,原创 2021-04-05 11:15:41 · 442 阅读 · 0 评论