09 2020 档案
摘要:概述 上篇文章简单介绍了和线程池相关的类和接口,本文就详细介绍下其中一个类ThreadPoolExecutor,该类实现了线程池的功能,其基本原理就是使用一个HashSet集合存放Worker,Worker也实现了Runnable接口,重写了run方法,所以可认为这就是一个线程。如果设置线程池线程数
阅读全文
摘要:概述 随着摩尔定律失效,多核计算器成为主流,多线程提高执行效率就变得异常重要,而线程的创建销毁又是一个开销比较大的操作,于是就产生了线程池,把使用过的线程放入线程池中,重复利用,其思想就是这些,很简单,但是线程池的管理就没有那么简单了,首先要管理好多个线程,然后还要管理任务,所以整个事情就变得复杂起
阅读全文
摘要:概述 LinkedBlockingQueue也是一个阻塞队列,相比于ArrayBlockingQueue,他的底层是使用链表实现的,而且是一个可有界可无界的队列,在生产和消费的时候使用了两把锁,提高并发,是一个高效的阻塞队列,下面就分析一下这个队列的源码。 属性 //链表节点定义 static cl
阅读全文
摘要:概述 在上篇文章的结构图中可以看出,所有的队列最后都实现了Queue接口,而Queue继承了Collection接口,而Collection接口继承了Iterable,由于不同的集合会根据自己集合的特性实现自己的迭代器,那本文就分析一下ArrayBlockingQueue集合迭代器的实现方式,因为之
阅读全文
摘要:概述 ArrayBlockingQueue是一个阻塞队列,其实底层就是一个数组,说到底层是数组,ArrayList底层也是数组,那它其实也可以作为队列,但是是非阻塞的,那阻塞和非阻塞的区别是什么?区别在于当队列中没有元素的时候就阻塞等待,直到队列中有数据再消费,而如果队列满了之后(队列有界),生产者
阅读全文
摘要:概述 由于ConcurrentHashMap是一个高并发的集合,集合中增删就比较频繁,那计数就变成了一个问题,如果使用像AtomicInteger这样类型的变量来计数,虽然可以保证原子性,但是太多线程去竞争CAS,自旋也挺浪费时间的,所以ConcurrentHashMap使用了一种类似LongAdd
阅读全文
摘要:概述 在上一篇文章中介绍了ConcurrentHashMap的存储结构,以及put和get方法,那本篇文章就介绍一下其扩容原理。其实说到扩容,无非就是新建一个数组,然后把旧的数组中的数据拷贝到新的数组中,在HashMap的实现中,由于没有加锁,可能会同时有多个线程创建了多个数组,而且拷贝的时候也没有
阅读全文
摘要:概述 ConcurrentHashMap,一个线程安全的高性能集合,存储结构和HashMap一样,都是采用数组进行分桶,之后再每个桶中挂一个链表,当链表长度大于8的时候转为红黑树,其实现线程安全的基本原理是采用CAS + synchronized组合,当数组的桶中没有元素时采用CAS插入,相反,则采
阅读全文
摘要:概述 CyclicBarrier,一个同步辅助类,其作用是让一组线程到达公共屏障点时阻塞,直到最后一个线程也到达公共屏障点,屏障才会打开,而且该屏障(barrier)在这一组线程释放后可以重用,所以称为循环(Cyclic)的屏障(Barrier)。看功能和CountDownLatch一样,但是两者的
阅读全文
摘要:概述 ThreadLocal是面试非常高频的问题,在很多框架源码中都可以看到他的身影,比如Spring,ReentrantReadWriteLock,然后在平时的工作使用的却并不多,ThreadLocal要解决并不是多线程修改共享变量保证线程安全的问题,这个是通过悲观锁(比如synchronized
阅读全文
摘要:概述 看名称就知道,这是一个读写锁,看上去好像和ReentrantLock有点关系,其实和ReentrantLock没有啥关系,两个类之间不存在互相调用和继承的关系,既然有了ReentrantLock为啥还要搞一个ReentrantReadWriteLock,主要还是因为ReentrantLock一
阅读全文
摘要:概述 Thread是线程的意思,在Java中我们一般都说多线程,而没有提过多进程,而且大家都知道,java中的多线程是真正的多线程,可以使用多核并行处理,而像python的多线程就是伪多线程,只能说是并发处理,那大家有没有好奇,jvm虚拟机相对于操作系统来说是一个进程,如果一个进程只能占用一个cpu
阅读全文
摘要:本文承接上一篇文章:AQS-共享模式分析 概述 CountDownLatch是一个同步计数器,他允许一个或者多个线程在另外一组线程执行完成之前一直等待,基于AQS共享模式实现的,下面就先举一个简单例子,从例子入手分析CountDownLatch的原理。 例子 public class CountDo
阅读全文
摘要:本文承接上一篇:AQS-共享模式分析 概述 信号量Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,本质上是一种共享锁。举个例子,还是生产者消费者的例子,假设缓冲区的大小是100,然后可以实现多个生产者和消费者同时进行工作,只要100个资源没有使用完,生产者就
阅读全文
摘要:本文承接上一篇文章:AQS-独占模式分析 概述 一般我们在使用锁的时候,是要求两个线程之间严格互斥的,即一次只能一个线程获取到锁,但是在有些场景下是可以一次有多个线程获取到锁,当然这个时候不叫锁,换了一种说法,叫做资源。比如生产者消费者模型,实际上我们是可以让多个生产者和消费者同时工作的,如果使用互
阅读全文
摘要:概述 ReentrantLock是基于AQS独占模式实现的一种可重入锁,与synchronized不同的是,ReentrantLock提供了公平锁和非公平锁的选择。其本质是基于操作系统的管程实现的。本文就分析一下ReentrantLock的实现原理,由于AQS在AQS-独占模式分析已经介绍过,所以涉
阅读全文
摘要:概述 Condition的作用用一句话概括就是为了实现线程的等待(await)和唤醒(signal),多线程情况下为什么需要等待唤醒机制?原因是有些线程执行到某个阶段需要等待符合某个条件才可以继续执行,在之前学习操作系统的时候,有一个经典的场景就是在容量有限的缓冲区实现生产者消费者模型,如果缓冲区满
阅读全文
摘要:概述 AQS,全称为AbstractQueuedSynchronizer,位于java.util.concurrent.locks包下面,是我们常见的ReentrantLock、Semaphore、CountDownLatch、ThreadPoolExecutor这些处理并发的类的基础。AQS有两种
阅读全文
摘要:概述 cas即(compare and swap),比较并交换,在java并发中使用非常广泛,无论是ReenterLock内部的AQS,还是各种Atomic开头的原子类,都是基于cas实现的,java8的ConcurrentHashMap也使用了cas + synchronized进行实现,本文就介
阅读全文
摘要:概述 synchronized是面试最高频的问题,比较简单的问题就是synchronized用在静态方法和非静态方法上的区别,复杂的问题就牵涉到synchronized如何保证原子性、有序性、可见性,以及synchronized锁优化和锁升级过程等,本文就介绍一下以上问题的原理。本文不涉及源码,如果
阅读全文
摘要:概述 前面两篇文章聊了下MESI协议和java内存模型,但是都是介绍原理,没有介绍在语言级别到底是如何保证的线程安全,从本文开始就开始介绍java语言中常用的关键字和锁。本文先介绍一下volatile,这个关键字面试的时候很喜欢考察,其实面试并不是为了考察volatile的用法,而是为了考察java
阅读全文
摘要:概述 Java内存模型是屏蔽掉硬件和操作系统内存访问差异,实现在各个平台内存访问的一致性。本文就介绍一下Java内存模型原理,之后介绍一下并发编程中常见的原子性、可见性、有序性问题。 主内存和工作内存 由于内存和CPU性能的差异,所以现代计算机都使用多级缓存的方式来加快运算速度,也就是说CPU不能直
阅读全文