目录 前言 在多线程环境下,为了保证线程安全, 我们通常会对共享资源加锁操作,我们常用Synchronized关键字或者ReentrantLock 来实现,这两者加锁方式都是排他锁,即同一时刻最多允许一个线程操作,然而大多数场景中对共享资源读多于写,那么存在线程安全问题的是写操作(修改,添加,删除),我们是否应该考虑将读和写两个分开,只要运用合理,并发性能是不是可以提高,吞吐量增大呢? ReentrantReadWriteLock已经为我们实现了这种机制,我们一起来看它是怎样实现的吧! 1.读写…
AQS的源码分析 目录结构 1.什么是CAS ? 2.同步器类结构 3.CLH同步队列 4.AQS中静态内部类Node 5.方法分析 ​ 5.1.acquire(int arg ) ​ 5.2.release(int arg) 释放锁 6.总结 前言 在多线程环境下,我们一般会对临界区资源(共享资源)进行加锁,释放锁,保证同一时刻最多只有一个线程(独占模式),就如去公共厕所里,在使用一个小房间时会加锁避免自己在使用的时候,别人突然闯进来一样,引起不必要的麻烦,在使用完后,再打开锁,其他人才可使用…
目录 AQS的源码分析 该篇主要分析AQS的ConditionObject,是AQS的内部类,实现等待通知机制. 1.条件队列 条件队列与AQS中的同步队列有所不同,结构图如下: 两者区别: 1.链表结构不同,条件队列是单向链表,同步队列是双向链表. 2.两个队列中等待条件不同,条件队列中线程是已经获取到锁,主动调用await方法释放锁,挂起当前线程,等待某个条件(如IO,mq消息等),同步队列中的线程是等待获取锁,在获取锁失败后挂起等待锁可用. 两者联系: 当等待的某个条件完成,其他线程调用s…
Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 本文内容:读写锁 ReentrantReadWriteLock 的源码分析,基于 Java7/Java8. 阅读建议:虽然我这里会介绍一些 AQS 的知识,不过如果你完全不了解 AQS,看本文就有点吃力了. 目录 使用示例 ReentrantReadWriteLock 总览 源码分析 读锁获取 读…
一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁ReadLock和写锁WriteLock,可以通过这两种锁实现线程间的同步,下面开始进行分析. 二.ReentrantReadWriteLock数据结构 分析源码可以知道,ReentrantReadWriteLock底层是基于ReentrantLock和AbstractQueuedSynchroni…
ReentrantReadWriteLock  源码分析: 1:数据结构: 成员变量: private final ReentrantReadWriteLock.ReadLock readerLock; //读取锁 private final ReentrantReadWriteLock.WriteLock writerLock; //写入锁 final Sync sync;    //Sync 对象,继承AQS对象 2:构造函数: public ReentrantReadWriteLock()…
概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和Semaphore,AQS还可以混合两种模式使用,读写锁ReentrantReadWriteLock就是如此. 设想以下情景:我们在系统中有一个多线程访问的缓存,多个线程都可以对缓存进行读或写操作,但是读操作远远多于写操作,要求写操作要线程安全,且写操作执行完成要求对当前的所有读操作马上可见. 分析…
本文结构 读写锁简介:介绍读写锁.读写锁的特性以及类定义信息 公平策略及Sync同步器:介绍读写锁提供的公平策略以及同步器源码分析 读锁:介绍读锁的一些常用操作和读锁的加锁.解锁的源码分析 写锁:介绍写锁的一些常用操作和写锁的加锁.解锁的源码分析 总结:总结全文,附读写锁全部源码理解 读写锁简介 在之前的文章提到了可重入锁,这是一种排他锁,核心原理是同一时间只允许一个线程访问.除了排他锁还有一种共享锁,这种锁在同一时间支持多线程同时访问, 将排他锁和共享锁进行组合便有了读写锁.读写锁维护了一组锁…
此处源码分析,主要是基于读锁,非公平机制,JDK1.8. 问题: 1.ReentrantReadWriteLock是如何创建读锁与写锁? 2.读锁与写锁的区别是什么? 3.锁的重入次数与获取锁的线程数分别是用哪种方式记录的? 4.当队列中出现多个共享模式的线程节点连续排列时,那么当第一个共享模式的线程拿到锁之后,后面的共享线程节点怎么获取锁? 一.创建ReadLock. ReentrantReadWriteLock rrw = new ReentrantReadWriteLock(); publ…
ReentrantReadWriteLock包含两把锁,一是读锁ReadLock, 此乃共享锁, 一是写锁WriteLock, 此乃排它锁. 这两把锁都是基于AQS来实现的. 下面通过源码来看看ReentrantReadWriteLock是如何做到读读共享,读写互斥的. 1. 测试代码  import java.util.concurrent.CyclicBarrier; import java.util.concurrent.locks.ReentrantReadWriteLock; publ…
前言 上一篇讲解了 AQS 的独占锁部分(参看:ReentrantLock 源码分析以及 AQS (一)),这一篇将介绍 AQS 的共享锁,以及基于共享锁实现读写锁分离的 ReentrantReadWriteLock.(若是遇到之前讲过的方法,将不再赘述) 先思考一下,为什么我们用读写锁分离? 我们知道 ReentrantLock 用的是独占锁,不管线程是读还是写状态,都会阻塞,这无疑会降低并发量. 但是,我们知道多个线程同时去读数据的时候,并不会产生线程安全的问题,因为它们互不干扰.那么为什么…
背景: AbstractQueuedSynchronizer(AQS) public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable 介绍 提供一个框架,用于实现依赖先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量,事件等). 该类被设计为大多数类型的同步器的有用依据,这些同步器依赖于单个原子int值来表示状态. 子类…
一.背景 前文讲了HashMap的源码分析,从中可以看到下面的问题: HashMap的put/remove方法不是线程安全的,如果在多线程并发环境下,使用synchronized进行加锁,会导致效率低下: 在遍历迭代获取时进行修改(put/remove)操作,会导致发生并发修改异常(ConcurrentModificationException): 在JDK1.7之前,对HashMap进行put添加操作,会导致链表反转,造成链表回路,从而发生get死循环,(当然这个问题在JDK1.8被改进了按照…
我们知道在解决线程安全问题上使用 ReentrantLock 就可以,但是 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而实际情况下会有写少读多的场景,显然 ReentrantLock 满足不了需求,所以 ReentrantReadWriteLock 应运而生,ReentrantReadWriteLock 采用读写分离,多个线程可以同时获取读锁. 首先我们先看一下,ReentrantReadWriteLock 内部构造先看下它的类图结构如下图所示: 如上图可以看到读写锁内…
一.概念 A Future计算的结果. 提供方法来检查计算是否完成,等待其完成,并检索计算结果. 结果只能在计算完成后使用方法get进行检索,如有必要,阻塞,直到准备就绪. 取消由cancel方法执行. 提供其他方法来确定任务是否正常完成或被取消. 计算完成后,不能取消计算. 如果您想使用Future ,以便不可撤销,但不提供可用的结果,则可以声明Future<?>表格的类型,并返回null作为基础任务的结果. public interface Future<V> { //尝试取消…
代码在后面 读锁 = 共享锁 读锁写锁,公用一个Sync AQS state. 写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁,别人也不会进来获取锁. 写锁的获取跟ReentarntLock一样,每次加1,是一个独占锁,只要有人获取了锁,自己就去排队,排队时候节点是EXCLUSIVE的节点,入队方法acquireQueued和ReentarntLock一样,会设置OwnerThread. 读锁先获取锁,后面有读锁进来,多个读线程共存时候,第一个读线程设置firstReader,其余读线程…
一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁ReadLock和写锁WriteLock,可以通过这两种锁实现线程间的同步,下面开始进行分析. 二.ReentrantReadWriteLock数据结构 分析源码可以知道,ReentrantReadWriteLock底层是基于ReentrantLock和AbstractQueuedSynchroni…
一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看ArrayBlockingQueue源码会很容易,下面开始正文. 二.ArrayBlockingQueue数据结构 通过源码分析,并且可以对比ArrayList可知,ArrayBlockingQueue的底层数据结构是数组,数据结构如下 说明:ArrayBlockingQueue底层采用数据才存放数据,对数…
概要: ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞 注意这两个Condition即ReentrantLock的Condition:ReentrantLock的内部类Sync继承了AQS这个抽象类,Sync的newCondition()返回AQS的ConditionObject 关键:队列已经满时入队,将当前线程加入notFull这个Condition等待队列,唤醒等待notEmpty条件的线程. 关键:队列为空…
1.ReentrantReadWriterLock 基础 所谓读写锁,是对访问资源共享锁和排斥锁,一般的重入性语义为如果对资源加了写锁,其他线程无法再获得写锁与读锁,但是持有写锁的线程,可以对资源加读锁(锁降级):如果一个线程对资源加了读锁,其他线程可以继续加读锁. java.util.concurrent.locks中关于多写锁的接口:ReadWriteLock. public interface ReadWriteLock { /** * Returns the lock used for…
java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线程系列(三)之等待通知机制 java多线程系列(四)之ReentrantLock的使用 java多线程系列(五)之synchronized ReentrantLock volatile Atomic 原理分析 java多线程系列(六)之线程池原理及其使用 java多线程系列(七)---Ca…
一.简介 读写锁. 读锁之间是共享的. 写锁是独占的. 首先声明一点: 我在分析源码的时候, 把jdk源码复制出来进行中文的注释, 有时还进行编译调试什么的, 为了避免和jdk原生的类混淆, 我在类前面加了"My". 比如把ReentrantLock改名为了MyReentrantLock, 在源码分析的章节里, 我基本不会对源码进行修改, 所以请忽视这个"My"即可. 1. ReentrantReadWriteLock类里的字段 unsafe在这里是用来给TID_O…
转载:https://blog.csdn.net/tonywu1992/article/details/83419448 http://benjaminwhx.com/archives/ 1.简介 上篇我们介绍了ArrayBlockingQueue的相关方法的原理,这一篇我们来学习一下ArrayBlockingQueue的“亲戚” LinkedBlockingQueue.在集合框架里,想必大家都用过ArrayList和LinkedList,也经常在面试中问到他们之间的区别.ArrayList和A…
本文首发于cdream的个人博客,点击获得更好的阅读体验! 欢迎转载,转载请注明出处. 通常应用多线程技术时,我们并不会直接创建一个线程,因为系统启动一个新线程的成本是比较高的,涉及与操作系统的交互,而是使用线程池来对线程进行管理,尤其是有很多生命周期很短的线程,线程池会显著提升多线程程序的性能. 本文主要对线程池的源码进行分析,了解了源码,我们才能够更高效的使用线程池,同时出现异常时也能更容易的进行排查. 1.阅读本文时,务必开启IDE2.本文篇幅较大,可根据需要跳转到需要的章节阅读 一.线程…
http://www.cnblogs.com/skywang12345/p/3509954.html 线程池示例 在分析线程池之前,先看一个简单的线程池示例. 1 import java.util.concurrent.Executors; 2 import java.util.concurrent.ExecutorService; 3 4 public class ThreadPoolDemo1 { 5 6 public static void main(String[] args) { 7…
  线程是程序执行的最小单元,多线程是指程序同一时间可以有多个执行单元运行(这个与你的CPU核心有关). 在java中开启一个新线程非常简单,创建一个Thread对象,然后调用它的start方法,一个新线程就开启了. 那么执行代码放在那里呢?有两种方式:1. 创建Thread对象时,复写它的run方法,把执行代码放在run方法里.2. 创建Thread对象时,给它传递一个Runnable对象,把执行代码放在Runnable对象的run方法里. 如果多线程操作的是不同资源,线程之间不会相互影响,不…
Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我们拿Java线程(二)中的一个例子简单的实现一下和sychronized一样的效果,代码如下: public class LockTest { public static void main(String[] args) { final Outputter1 output = new Outputt…
前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现Runnable接口 AsyncTask Handler HandlerThread IntentService 今天,我将全面解析多线程其中一种常见用法:IntentService 目录 目录 1. 定义 IntentService是Android里面的一个封装类,继承自四大组件之一的Service. 2. 作用 处理异步请求,实现多线程 3. 工作流程 工作流程 注意:若启动IntentServi…
前言 这篇主要讲述ThreadPoolExecutor的源码分析,贯穿类的创建.任务的添加到线程池的关闭整个流程,让你知其然所以然.希望你可以通过本篇博文知道ThreadPoolExecutor是怎么添加任务.执行任务的,以及延伸的知识点.那么先来看看ThreadPoolExecutor的继承关系吧. 继承关系 Executor接口 public interface Executor { void execute(Runnable command); } Executor接口只有一个方法exec…
ReentrantLock源码分析 基础知识复习 synchronized和lock的区别 synchronized是非公平锁,无法保证线程按照申请锁的顺序获得锁,而Lock锁提供了可选参数,可以配置成公平锁,也可以配置成非公平锁.通常来说,非公平锁的效率比公平锁要高. 一个线程使用syn获取锁,除非该线程成功获取到锁,否则将一直阻塞住.而Lock锁提供了lockInterruptibly()接口,提供了可中断的操作 带超时时间的锁.Lock锁提供了tryLock(long time, Time…