聊聊高并发
文章平均质量分 86
这个系列涉及到了并发编程的原理,技术,算法,设计,底层实现,经验积累等方方面面
iter_zc
关注互联网架构方向
展开
-
聊聊高并发(四十四)解析java.util.concurrent各个组件(二十) Executors工厂类
Executor框架为了更方便使用,提供了Executors这个工厂类,通过一系列的静态工厂方法,可以快速地创建相应的Executor实例。只有一个nThreads参数的newFixedThreadPool方法会创建一个ThreadPoolExecutor,corePoolSize和maximumPoolSize都是nThreads,并且keepAliveTime为0表示不会设置过期时原创 2015-07-22 16:10:04 · 4089 阅读 · 1 评论 -
聊聊高并发(四十三)解析java.util.concurrent各个组件(十九) 任务的定时执行和周期执行
ExecutorService最后一块是定时/周期执行任务的接口ScheduledExecutorService。这篇说说ScheduledExecutorService相关的内容。ScheduledExecutorService接口扩展了ExecutorService接口,在ExecutorService的生命周期管理,异步执行任务,批量执行任务的基础上,扩展了定时/周期执行任务的能力。原创 2015-07-21 16:15:49 · 5008 阅读 · 0 评论 -
聊聊高并发(四十二)解析java.util.concurrent各个组件(十八) 任务的批量执行和CompletionService
上一篇讲了ExecutorService关于任务的异步执行和状态控制的部分,这篇说说关于任务批量执行的部分。ExecutorSerivce中关于批量执行的原创 2015-07-20 15:16:48 · 4082 阅读 · 0 评论 -
聊聊高并发(四十一)解析java.util.concurrent各个组件(十七) 任务的异步执行和状态控制
这篇接着说ExecutorService相关内容。聊聊高并发(三十九)解析java.util.concurrent各个组件(十五) 理解ExecutorService接口的设计这篇说了ExecutorService接口扩展了Executor接口,在执行任务的基础上,提供了执行框架生命周期的管理,任务的异步执行,批量任务的执行的能力。AbstractExecutorService抽象类实现了Exec原创 2015-07-17 15:17:23 · 4221 阅读 · 0 评论 -
聊聊高并发(四十)解析java.util.concurrent各个组件(十六) ThreadPoolExecutor源码分析
ThreadPoolExecutor是Executor执行框架最重要的一个实现类,提供了线程池管理和任务管理是两个最基本的能力。这篇通过分析ThreadPoolExecutor的源码来看看如何设计和实现一个基于生产者消费者模型的执行器。生产者消费者模型生产者消费者模型包含三个角色:生产者,工作队列,消费者。对于ThreadPoolExecutor来说,1. 生产者是任务的提原创 2015-07-16 16:27:08 · 5038 阅读 · 2 评论 -
聊聊高并发(三十九)解析java.util.concurrent各个组件(十五) 理解ExecutorService接口的设计
上一篇讲了Executor接口的设计,目的是将任务的执行和任务的提交解耦,可以隐藏任务的执行策略。这篇说说ExecutorService接口。它扩展了Executor接口,对Executor的生命周期进行管理,并进行了进一步的扩展。Executor负责执行任务。它的生命周期有3个:运行,关闭和已终止。在运行的任何时刻,有些 任务可能已经完成,有些可能正在运行,有些可能正在队列中等待执行原创 2015-06-26 17:22:40 · 2903 阅读 · 0 评论 -
聊聊高并发(三十八)解析java.util.concurrent各个组件(十四) 理解Executor接口的设计
JCU包中除了一系列的同步类之外,就是Executor执行框架相关的类。对于一个执行框架来说,可以分为两部分1. 任务的提交2. 任务的执行。Executor接口设计的目的是专注于任务的执行,和任务的提交解耦。Executor接口封装了任务执行的细节,比如如何使用线程,是否定时执行等等。Executor接口很简单,就一个execute方法。public interface原创 2015-06-25 17:33:15 · 2937 阅读 · 0 评论 -
聊聊高并发(三十七)整理一下并发基础中的一些知识点
最近在准备并发基础的PPT,想到了一些知识点,记录下来以后也可以做个参考。大部分的知识点在之前的博客中都多少涉及到了这里的并发基础指的是单机多处理器的情况下的一些并发问题,不涉及到分布式环境下的并发问题。并发基础主要解决的是可见性,有序性和原子性的问题,让不可控的进程/线程变得可以预测,可以控制行为。Java解决可见性/有序性的主要技术是通过Java内存模型来解决的。J原创 2014-12-23 13:09:23 · 6782 阅读 · 1 评论 -
聊聊高并发(三十六)Java内存模型那些事(四)理解Happens-before规则
在前几篇将Java内存模型的那些事基本上把这个域底层的概念都解释清楚了,聊聊高并发(三十五)Java内存模型那些事(三)理解内存屏障 这篇分析了在X86平台下,volatile,synchronized, CAS操作都是基于Lock前缀的汇编指令来实现的,关于Lock指令有两个要点:1. lock会锁总线,总线是互斥的,所以lock后面的写操作会写入缓存和内存,可以理解为在lock后面的写缓存原创 2014-12-19 11:53:35 · 7352 阅读 · 13 评论 -
聊聊高并发(三十五)Java内存模型那些事(三)理解内存屏障
在聊聊高并发(三十三)从一致性(Consistency)的角度理解Java内存模型 我们说了硬件层提供了满足某些一致性需求的能力,Java内存模型利用了硬件层提供的能力指定了一系列的语法和规则,让Java开发者可以隔绝这种底层的实现专注于并发逻辑的开发。这篇我们来看看硬件层是如何提供这些实现一致性需求的能力的。硬件层提供了一系列的内存屏障 memory barrier / memory原创 2014-12-18 16:08:03 · 13705 阅读 · 4 评论 -
聊聊高并发(三十四)Java内存模型那些事(二)理解CPU高速缓存的工作原理
在上一篇聊聊高并发(三十三)从一致性(Consistency)的角度理解Java内存模型 我们说了Java内存模型是一个语言级别的内存模型抽象,它屏蔽了底层硬件实现内存一致性需求的差异,提供了对上层的统一的接口来提供保证内存一致性的编程能力。在一致性这个问题域中,各个层面扮演的角色大致如下:1. 一致性模型,定义了各种一致性模型的理论基础2. 硬件层,提供了实现某些一致性模型的硬件能力原创 2014-12-17 11:06:34 · 15239 阅读 · 3 评论 -
聊聊高并发(三十三)Java内存模型那些事(一)从一致性(Consistency)的角度理解Java内存模型
可以说并发系统要解决的最核心问题就是一致性的问题,关于一致性的研究已经有几十年了,有大量的理论,算法支持。这篇说说一致性这个主题一些经常提到的概念,理清Java内存模型在其中的位置。一致性问题在单机器单CPU的情况下是最简单的,由于只有一个CPU,所有的读写操作都可以按照全局的时间顺序执行在单机器多CPU的情况下,多CPU并发执行,公用一个内存,一般通过共享内存的方式来处理一致性问原创 2014-12-15 14:31:07 · 10986 阅读 · 1 评论 -
聊聊高并发(三十二)实现一个基于链表的无锁Set集合
Set表示一种没有重复元素的集合类,在JDK里面有HashSet的实现,底层是基于HashMap来实现的。这里实现一个简化版本的Set,有以下约束:1. 基于链表实现,链表节点按照对象的hashCode()顺序由小到大从Head到Tail排列。2. 假设对象的hashCode()是唯一的,这个假设实际上是不成立的,这里为了简化实现做这个假设。实际情况是HashCode是基于对象地址进行的一原创 2014-11-14 10:51:54 · 7486 阅读 · 1 评论 -
聊聊高并发(三十一)解析java.util.concurrent各个组件(十三) 理解Exchanger交换器
这篇讲讲Exchanger交互器,它是一种比较特殊的两方(Two-Party)栅栏,可以理解成Exchanger是一个栅栏,两边一方是生产者,一方是消费者,1. 生产者和消费者各自维护了一个容器,生产者往容器里生产东西,消费者从容器里消费东西。2. 当生产者的容器是满的时候,它需要通过Exchanger向消费者交换,把满的容器交换给消费者,从消费者手里拿到空的容器继续生产。3. 当消费原创 2014-11-12 18:04:35 · 3076 阅读 · 0 评论 -
聊聊高并发(三十)解析java.util.concurrent各个组件(十二) 理解CyclicBarrier栅栏
这篇讲讲CyclicBarrier栅栏,从它的名字可以看出,它是可循环使用的。它的功能和CountDownLatch类似,也是让一组线程等待,然后一起开始往下执行。但是两者还是有几个区别1. 等待的对象不同。CountDownLatch的一组线程等待的是一个事件,或者说是一个计数器归0的事件。而CyclicBarrier等待的对象是线程,只有线程都到齐了才往下执行2. 使用方式不同,这个也原创 2014-11-12 14:00:10 · 4294 阅读 · 0 评论 -
聊聊高并发(二十九)解析java.util.concurrent各个组件(十一) 再看看ReentrantReadWriteLock可重入读-写锁
上一篇聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁 讲了可重入读写锁的基本情况和主要的方法,显示了如何实现的锁降级。但是下面几个问题没说清楚,这篇补充一下1. 释放锁时的优先级问题,是让写锁先获得还是先让读锁先获得2. 是否允许读线程插队3. 是否允许写线程插队,因为读写锁一般用在大量原创 2014-11-12 10:38:18 · 3217 阅读 · 0 评论 -
聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁
这篇讲讲ReentrantReadWriteLock可重入读写锁,它不仅是读写锁的实现,并且支持可重入性。原创 2014-11-11 17:37:28 · 4271 阅读 · 0 评论 -
聊聊高并发(二十七)解析java.util.concurrent各个组件(九) 理解ReentrantLock可重入锁
这篇讲讲ReentrantLock可重入锁,JUC里提供的可重入锁是基于AQS实现的阻塞式可重入锁。这篇 聊聊高并发(十六)实现一个简单的可重入锁 模拟了可重入锁的实现。可重入锁的特点是:1. 是互斥锁,基于AQS的互斥模式实现,也就是说同时只有一个线程进入临界区,唤醒下一个线程时也只能释放一个等待线程2. 可重入,通过设置了一个字段exclusiveOwnerThread来标示当前获原创 2014-11-11 15:46:07 · 3656 阅读 · 0 评论 -
聊聊高并发(二十六)解析java.util.concurrent各个组件(八) 理解CountDownLatch闭锁
CountDownLatch闭锁也是基于AQS实现的一种同步器,它表示了“所有线程都等待,直到锁打开才继续执行”的含义。它和Semaphore的语意不同, Semaphore的获取和释放操作都会修改状态,都可能让自己或者其他线程立刻拿到锁。而闭锁的获取操作只判断状态是否为0,不修改状态本身,闭锁的释放操作会修改状态,每次递减1,直到状态为0。所以正常情况下,闭锁的获取操作只是等待,不会立刻让自原创 2014-11-11 14:06:47 · 3498 阅读 · 0 评论 -
聊聊高并发(二十五)解析java.util.concurrent各个组件(七) 理解Semaphore
前几篇分析了一下AQS的原理和实现,这篇拿Semaphore信号量做例子看看AQS实际是如何使用的。Semaphore表示了一种可以同时有多个线程进入临界区的同步器,它维护了一个状态表示可用的票据,只有拿到了票据的线程尽可以进入临界区,否则就等待,直到获得释放出的票据。Semaphore常用在资源池中来管理资源。当状态只有1个0两个值时,它退化成了一个互斥的同步器,类似锁。原创 2014-11-11 11:15:38 · 3918 阅读 · 0 评论 -
聊聊高并发(二十四)解析java.util.concurrent各个组件(六) 深入理解AQS(四)
本来在这篇聊聊高并发(二十三)解析java.util.concurrent各个组件(五) 深入理解AQS(三) 中想结束AQS的话题, 但是最近在网上原创 2014-11-10 11:49:17 · 4666 阅读 · 0 评论 -
聊聊高并发(二十三)解析java.util.concurrent各个组件(五) 深入理解AQS(三)
这篇对AQS做一个总结。上一篇帖了很多AQS的代码,可以看出AQS的实现思路很简单,就是提供了获取accquire和释放操作release,提供了1. 可中断和不可中断的版本2. 可定时和不可定时的版本3. 独享和共享的版本看过之前实现各种自旋锁系列的同学应该知道,在自旋锁的实现中,获取锁和释放锁操作的逻辑基本如下:自旋锁获取锁操作while 状态不允许获取原创 2014-11-07 10:10:38 · 3802 阅读 · 0 评论 -
聊聊高并发(二十二)解析java.util.concurrent各个组件(四) 深入理解AQS(二)
上一篇介绍了AQS的基本两个内部类Node和ConditionObject的实现原创 2014-11-06 21:38:47 · 5181 阅读 · 2 评论 -
聊聊高并发(二十一)解析java.util.concurrent各个组件(三) 深入理解AQS(一)
AQS是AbstractQueuedSynchronizer的缩写,AQS是Java并包里大部分同步器的基础构件,利用AQS可以很方便的创建锁和同步器。它封装了一个状态,提供了一系列的获取和释放操作,这些获取和释放操作都是基于状态的。它的基本思想是由AQS负责管理同步器类中的状态,其他的同步器比如可重入锁ReentrantLock, 信号量Semaphore基于各自的特点来调用AQS提供了基础能力原创 2014-11-06 14:16:49 · 6618 阅读 · 0 评论 -
聊聊高并发(二十)解析java.util.concurrent各个组件(二) 12个原子变量相关类
这篇说说java.util.concurrent.atomic包里的类,总共12个,网上有很多文章解析这几个类,这里挑些重点说说。这12个类可以分为三组:1. 普通类型的原子变量2. 数组类型的原子变量3. 域更新器普通类型的原子变量的6个,1. 其中AtomicBoolean, AtomicInteger, AtomicLong, AtomicRe原创 2014-11-04 10:49:05 · 3965 阅读 · 0 评论 -
聊聊高并发(十九)理解并发编程的几种"性" -- 可见性,有序性,原子性
这篇的主题本应该放在最初的几篇,讨论的是并发编程最基础的几个核心概念,但是这几个概念又牵扯到很多的实际技术,比如Java内存模型,各种锁的实现,volatile的实现,原子变量等等,每一个都可以展开写很多,尤其是Java内存模型,网上已经能够有很几篇不错的文章,暂时不想重复造轮子,这里推荐几篇Jave内存模型的资料:1. JSR-133 FAQ2. JSR-133 Cookbook原创 2014-11-03 21:43:16 · 5939 阅读 · 1 评论 -
聊聊高并发(十八)理解AtomicXXX.lazySet方法
看过java.util.concurrent.atomic包里面各个AtomicXXX类实现的同学应该见过lazySet方法,比如AtomicBoolean类的lazySet方法public final void lazySet(boolean newValue) { int v = newValue ? 1 : 0; unsafe.putOrderedInt(原创 2014-11-03 18:10:06 · 8641 阅读 · 0 评论 -
聊聊高并发(十七)解析java.util.concurrent各个组件(一) 了解sun.misc.Unsafe类
了解了并发编程中锁的基本原理之后,接下来看看Java是如何利用这些原理来实现各种锁,原子变量,同步组件的。在开始分析java.util.concurrent的源代码直接,首先要了解的就是sun.misc.Unsafe类,这个类可以说的java并发包的基础,基本上所有的组件都是依赖Unsafe来做底层的同步操作。Unsafe类有100+个方法,大部分是native方法,可以理解为Java原创 2014-11-03 16:14:23 · 5045 阅读 · 0 评论 -
聊聊高并发(十六)实现一个简单的可重入锁
可重入锁指的是如果一个线程已经获得了一个锁,那么它可以多次进入这个锁,当然前提是线程需要先获得这个锁。可重入锁是最常使用的锁,Java的内置锁就是可重入锁,使用synchronized关键字可以启用内置锁机制,比如说一个类有两个synchronized方法A和B,在A方法中调用了B方法,如果锁不是可重入的,那么访问B时需要再次竞争锁,这样会带来死锁。 public synch原创 2014-11-03 14:08:45 · 5142 阅读 · 2 评论 -
聊聊高并发(十五)实现一个简单的读-写锁(共享-排他锁)
读写锁是数据库中很常见的锁,又叫共享-排他锁,S锁和X锁。读写锁在大量读少量写的情况下有很高的效率优势。读写锁是基于普通的互斥锁构建出来的更复杂的锁,它有两个基本特点:1. 当任一线程持有读锁或写锁时,不允许其他线程再持有写锁2. 当任一线程持有写锁时,不允许其他线程再持有读锁也就是说,写锁是排他的,只要有一个线程持有写锁,就不允许其他线程再上锁。读锁是共享的,可以有多个线原创 2014-11-03 11:47:30 · 7754 阅读 · 8 评论 -
聊聊高并发(十四)理解Java中的管程,条件队列,Condition以及实现一个阻塞队列
第一次看到管程这个中文名称很原创 2014-10-31 11:34:56 · 8781 阅读 · 0 评论 -
聊聊高并发(十三)实现几种自旋锁(六)
聊聊高并发(十一)实现几种自旋锁(五) 给出了限时有界队列锁的lock和unlock实现,这篇给出tryLock的实现tryLock比lock稍微复杂一点,要处理超时的情况。超时有几种情况:1. 第一步在等待队列还没有获得节点的时候超时,直接返回false即可2. 第二步在等待队列已经获得节点但是还没有加入工作队列时超时,把节点状态可以直接改成FREE给后续线程使用,然后返回f原创 2014-10-30 16:21:11 · 3650 阅读 · 0 评论 -
聊聊高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference源码来看如何解决CAS的ABA问题
在聊聊高并发(十一)实现几种自旋锁(五)中使用了java.util.concurrent.atomic.AtomicStampedReference原子变量指向工作队列的队尾,为何使用AtomicStampedReference原子变量而不是使用AtomicReference是因为这个实现中等待队列的同一个节点具备不同的状态,而同一个节点会多次进出工作队列,这就有可能出现出现ABA问题。原创 2014-10-30 12:29:58 · 7602 阅读 · 0 评论 -
聊聊高并发(十一)实现几种自旋锁(五)
在聊聊高并发(九)实现几种自旋锁(四)中实现的限时队列锁是一个基于链表的限时无界队列锁,它的tryLock方法支持限时操作和中断操作,无饥饿,保证了先来先服务的公平性,在多个共享状态上自旋,是低争用的。但是它的一个缺点是牺牲了空间,为了让线程可以多次使用锁,每次Lock的时候都要new QNode,并设置给线程,而不能重复使用原来的节点。这篇说说限时有界队列锁,它采用了有界队列,并原创 2014-10-30 11:26:02 · 5052 阅读 · 2 评论 -
聊聊高并发(十)利用自旋原理来无锁实现“只创建一次”的场景
相信看过之前几篇自旋锁实现的同学对设计一个自旋锁会有一定的感觉,有几个实现的要点很实用:1. 使用AtomicBoolean原子变量的getAndSet(true)方法来实现并发情况下,找到第一个成功执行方法的线程。这个技巧经常使用,在并发编程中经常会遇到这种需求2.经常会使用volatile boolean类型的变量在多个线程之间同步状态,需要注意的是,对volatile变量的修改只具有原创 2014-10-28 17:38:44 · 6855 阅读 · 4 评论 -
聊聊高并发(九)实现几种自旋锁(四)
这篇看一下时限队列锁的一种实现方式。 java并发包中的Lock定义包含了时限锁的接口:public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long t原创 2014-10-27 11:57:55 · 4641 阅读 · 0 评论 -
聊聊高并发(八)实现几种自旋锁(三)
在聊聊高并发(七)实现几种自旋锁(二) 这篇中介绍了两种队列锁,原创 2014-10-23 16:01:16 · 5338 阅读 · 4 评论 -
聊聊高并发(七)实现几种自旋锁(二)
在聊聊高并发(六)实现几种自旋锁(一) 这篇中实现了两种基本的自旋锁:TASLock和TTASLock,它们的问题是会进行频繁的CAS操作,引发大量的缓存一致性流量,导致锁的性能不好。对TTASLock的一种改进是BackoffLock,它会在锁高争用的情况下对线程进行回退,减少竞争,减少缓存一致性流量。但是BackoffLock有三个主要的问题:1. 还是有大量的缓存一致性流量,原创 2014-10-23 10:31:51 · 6551 阅读 · 8 评论 -
聊聊高并发(六)实现几种自旋锁(一)
在聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响 我们了解了处理器缓存一致性协议的原理,并且提到了它对并发编程的影响,“多个线程对同一个变量一直使用CAS操作,那么会有大量修改操作,从而产生大量的缓存一致性流量,因为每一次CAS操作都会发出广播通知其他处理器,从而影响程序的性能。”这一篇我们通过两种实现自旋锁的方式来看一下不同的编程方式带来的程序性能的变化。先理解一原创 2014-10-22 11:39:05 · 12202 阅读 · 5 评论 -
聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响
Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者一个一致的使用接口。Java内存模型就是这样一个中间层的模型,它为程序员屏蔽了底层的硬件实现细节,支持大部分的主流硬件平台。要理解Java内存模型以及一些处理高并发的技术手段,理解一些基本的硬件知识是必须的。这篇会说一下跟并发编程相关的一些硬件知识。一个基本的CPU执行原创 2014-10-21 11:55:35 · 13632 阅读 · 7 评论