《Java并发编程的艺术》知识点目录
Java并发编程的艺术
第一章 并发编程的挑战
1.1 上下文切换
- p1 上下文切换
- p1 多线程一定快吗
- p3 为什么并发执行的速度有时比串行慢
- p3 测试上下文切换次数和时长
- p3 如何减少上下文切换
- P4 减少上下文切换实战
1.2 死锁
- p5 死锁
- p6 避免死锁的几个常见方法
- 1.3 资源限制的挑战
- p6 资源限制
第二章 Java并发机制的底层实现原理
2.1 volatile的应用
- p8 volatile的定义
- p9 一些有关volatile实现原理的cpu术语的定义
- p9 volatile是如何实现可见性的
- p9 Lock前缀指令在多核处理器下引发的事情
- p10 volatile的两条实现原则
- p10 缓存一致性和缓存锁定
- p11 追加64字节来为volatile优化性能(解决伪共享问题)
- p11 不应该追加到64字节的情况
2.2 synchronized的实现原理与应用
- p12 Java中的每一个对象都可以作为锁
- p12 synchonized在JVM中的实现原理
- p12 Java对象头及其数据组成
- p13 锁的升级与对比
- p13 JavaSE1.6以后锁的四种状态级别
- p13 偏向锁
- p13 偏向锁的定义、使用和撤销
- p14 偏向锁获得和撤销的流程图
- p14 利用JVM关闭偏向锁的延迟和彻底关闭偏向锁
- p15 轻量级锁
- p15 轻量级锁的加锁和解锁
- p15 轻量级锁的自旋
- P15 争夺锁导致的锁膨胀流程图
- p16 偏向锁、轻量级锁、重量级锁优缺点的对比
2.3 原子操作的实现原理
- p16 缓存行、比较并交换、CPU流水线、内存顺序冲突定义
- p17 处理器如何实现原子操作
- p17 使用总线锁保证原子性
- p17 使用缓存锁保证原子性
- P18 使用循环CAS实现原子操作
- p19 CAS实现原子操作的三大问题(ABA、循环时间长开销大、只能保证一个共享变量的原子操作)
- p20 处理器提供的pause指令
- p20 使用锁机制实现原子操作
第三章 Java内存模型
3.1 Java内存模型的基础
- p21 并发编程模型的两个关键问题
- p21 线程通信的两种方式及Java所使用的共享内存模型
- p22 Java内存模型的抽象结构
- p22 JMM如何控制Java线程通信
- p22 JMM控制下两个线程通信所必须的步骤
- p23 从源代码到指令序列的重排序
- P24 内存屏障概念(通过指令禁止特定类型的重排序)
- p24 并发编程模型的分类
- p24 写缓冲区及其特性
- p25 处理器的重排序规则
- p26 内存屏障类型表
- p26 happens-before简介
- p27 happens-before与JMM关系
3.2 重排序
- p28 数据依赖性
- p28 as-if-serial语义
- p29 程序顺序规则
- p29 重排序对多线程的影响
- p31 控制依赖关系
- p31 编译器和处理器的猜测
- p31 重排序缓冲
3.3 顺序一致性
- p31 数据竞争与顺序一致性
- p31 数据竞争
- p32 顺序一致性
- p32 顺序一致性内存模型
- p33 读/写操作串行化
- p34 程序的顺序一致性结果
- p35 未同步程序的执行特性
- p36 未同步程序在顺序一致性模型和JMM中执行的差异
- p36 总线事务
- p37 JVM不被强求对64位浮点数的写操作具有原子性
3.4 volatile的内存语义
- p38 volatile的特性
- p39 volatile写-读建立的happens-before关系
- p39 volatile写-读建立的内存语义
- p40 volatile写的内存语义
- p41 volatile读的内存语义
- p42 volatile内存语义的实现
- p42 volatile重排序规则表
- p43 volatile中基于保守策略的JMM内存屏障插入策略
- p44 为什么要在volatile写的后面插入一个StoreLoad屏障
- p44 编译器自动省略不必要的屏障
- p45 X86处理器仅对写-读操作做重排序
- p46 JSR-133为什么要增强volatile的内存语义
- p47 volatile和锁的对比
3.5 锁的内存语义
- p47 锁的释放-所建立的happens-before关系
- p48 锁的释放和获取的内存语义
- p50 锁内存语义的实现
- p50 ReentrantLock的实现依赖于Java同步框架AQS
- p51 公平锁加锁调用轨迹
- p52 公平锁解锁调用轨迹
- p52 非公平锁的内存语义实现
- p52 CAS
- P53 CAS是如何同时具有volatile读和volatile写的内存语义的
- p53 intel手册对lock前缀的说明
- p54 公平锁和非公平锁内存语义总结
- p54 锁释放-获取内存语义的两种实现
- p54 Concurrent包的实现
- p54 Java线程通信的四种方式
- p54 concurrent包的通用化实现模式
- p55 concurrent包的实现示意图
3.6 final域的内存语义
- p55 final域的重排序规则
- p55 对于final域,编译器和处理器要遵守的两个重排序规则
- p56 写final域的重排序规则
- p57 读final域的重排序规则
- p59 final域为引用类型时的重排序规则
- p59 为什么final域不能从构造函数中“溢出”
- p62 JSR-133为什么要增强final的语义
3.7 happens-before
- p62 JMM的设计
- p62 设计JMM时需要考虑的关键因素
- p63 JMM对两种不同类型重排序的不同策略
- p63 JMM设计示意图
- p64 happens-before的定义
- p65 happens-before规则
- p66 start()规则
- p66 join()规则
3.8 双重检查锁定与延迟初始化
- p67 延迟初始化
- p68 双重检查锁定(一个错误的优化)
- p69 问题的根源
- p69 intra-thread semantics(允许单线程中不影响结果的重排序)
- p71 两个方法实现线程安全的延迟初始化
- p71 基于volatile-利用双重检查锁定实现延迟初始化
- p72 基于类初始化过程中的锁实现延迟初始化
- p73 类和接口的初始化时机
- p73 类和接口的初始化锁LC
- p73 类和接口的初始化过程(五个阶段,下面不再列举)
- p78 对比基于volatile的双重检查锁定的方案和基于类初始化的方案
3.9 Java内存模型综述
- p78 处理器的内存模型
- p79 TSO、PSO、RMO、PowerPC内存模型
- p79 处理器内存模型特征表
- p80 JMM插入内存屏障的示意图
- p80 各种内存模型之间的关系
- p80 以程序类型分类,三种JMM的内存可见性保证
- p81 为未同步程序提供的最小安全性保障
- p81 各种CPU内存模型的强弱对比示意图
- p81 JSR-133 对 JDK5 之前的旧内存模型的修补
- p82 不同内存可见性的三类程序的执行结果对比
第四章 Java并发编程基础
4.1 线程简介
- p83 什么是线程
- p84 为什么要使用多线程(更多的处理器核心、更快的响应时间、更好的编程模型)
- p85 什么是线程优先级
- p85 设置线程优先级的规律
- p86 线程优先级不能作为程序正确性的依赖
- p87 线程的状态
- p89 Java线程状态变迁图
- p90 Daemon线程(守护线程)
4.2 启动和终止线程
- p91 构造线程
- p92 初始化线程对象
- p92 启动线程
- p92 理解中断
- p92 抛出InterruptedException之前会清除中断标识位
- p93 过期的suspend()、resume()和stop()
- p95 安全地终止线程
4.3 线程间通信
- p96 volatile和synchronized关键字
- p96 每个线程可以拥有对象/对象的成员变量的拷贝
- p96 volatile的作用
- p96 synchronized的作用
- p97 synchronized关键字的实现细节
- p97 对象的监视器(monitor)
- p98 对象、监视器、同步队列和执行线程之间的关系
- p98 等待/通知机制
- p99 等待/通知相关方法
- p100 调用wati()、notify()和notifyAll()时需要注意的细节
- p101 等待/通知基本范式(生产者消费者问题)
- p102 管道输入/输出流(piped)
- p103 Thread.join()的使用
- p105 ThreadLocal的使用
4.4 线程应用实例
- p106 等待超时模式
- p106 一个简单的数据库连接池示例
- p110 线程池技术及其示例
- p114 一个基于线程池技术的简单Web服务器
第五章 Java中的锁
5.1 Lock接口
- p120 Lock的使用方式
- p120 Lock提供的synchoronized没有的特征(非阻塞获取锁、被中断地获取锁、超时获取锁)
- p120 Lock的API
5.2 队列同步器
- p121 队列同步器AbstractQueuedSynchronizer
- p121 同步器提供的三个基本方法 — getState()、setState()和compareAndSetState()
- p121 锁和同步器的关系
- p121 队列同步器的接口与示例
- p121 同步器可重写的方法
- p122 同步器提供的模板方法
- p122 独占锁
- p124 队列同步器的实现分析
- p124 同步队列
- p124 同步队列中的节点,及其属性类型与名称及描述
- p125 同步队列的基本结构
- p126 独占式同步状态获取与释放
- p128 独占式同步状态获取流程
- p129 共享式同步状态获取与释放
- p131 独占式超时获取同步状态
- p133 自定义同步组件 - TwinsLock
- p134 自定义同步器定义为自定义同步组件的内部类
5.3 重入锁
- p136 重入锁ReentrantLock
- p136 锁获取的公平性问题
- p136 重进入的实现
- p137 公平与非公平获取锁的区别
5.4 读写锁
- p140 读写锁
- p141 读写锁的接口与示例
- p141 ReentrantReadWriteLock
- p142 读写锁的实现分析
- p142 一个整型变量上维护多种状态 - 按位切割使用
- P145 锁降级
5.5 LockSupport工具
- p146 LockSupport提供的阻塞和唤醒方法
- p147 阻塞对象Blocker在LockSupport中的作用(由dump体现)
5.6 Condition接口
- p147 Object的监视器方法与Condition接口的对比
- p148 Condition接口与示例
- p148 调用Condition的方法前应该先获取锁
- p148 Condition的部分方法以及描述
- p149 有界队列
- p150 Condition的实现分析
- p151 await和signal的实质
第六章 Java并发容器和框架
6.1 ConcurrentHashMap的实现原理与使用
- p155 为什么要使用ConcurrentHashMap
- p156 锁分段技术
- p156 ConcurrentHashMap的结构
- p157 ConcurrentHashMap的初始化
- p159 在分段锁中定位Segment
- P160 ConcurrentHashMap的操作(get、put、size)
- p160 ConcurrentHashMap的get方法里将共享变量定义为volatile
6.2 ConcurrentLinkedQueue
- p161 实现线程安全的队列的方法
- p162 ConcurrentLinkedQueue的结构
- p162 入队列
- p165 HOPS的设计意图
- p163 出队列
6.3 Java中的阻塞队列
- p167 什么是阻塞队列
- p167 阻塞队列不可用时由不同方法提供的四种处理方式
- p168 JDK7提供的7个阻塞队列
- P168 队列ArrayBlockingQueue - 数组结构组成的有界阻塞队列
- p169 队列LinkedBlockingQueue - 链表实现的(伪)有界阻塞队列
- p169 队列PriorityBlockingQueue - 支持优先级的有界阻塞队列
- p169 队列DelayQueue - 支持延时获取元素的无界等待队列
- p171 队列SynchronousQueue - 不存储元素的阻塞队列
- p171 队列LinkedTransferQueue - 由链表结构组成的无界阻塞队列
- p172 队列LinkedBlockingDeque - 链表结构组成的双向阻塞队列
- p172 阻塞队列的实现原理
- p174 native方法unsafe.park
- p174 JVM实现park方法
6.4 Fork/Join框架
- p175 什么是Fork/Join框架
- p176 工作窃取算法
- p177 Fork/Join框架的设计
- p177 RecursiveAction和RecursiveTask
- p177 使用Fork/Join框架
- p179 Fork/Join框架的异常处理
- p179 Fork/Join框架的实现原理
第七章 Java中的12个原子操作类
- p182 Atomic包
7.1 原子更新基本类型类
- p182 三种原子更新基本类型类(Boolean、Integer、Long)
- p184 如何原子更新其他的基本类型
7.2 原子更新数组
- p184 三种原子更新数组(Integer、Long、Reference)
- p185 AtomicIntegerArray对内部元素修改时,不影响构造时传入的数组
7.3 原子更新引用类型
- p185 三种原子更新引用类型(Reference、ReferenceFieldUpdater、MarkableReference)
7.4 原子更新字段类
- P187 三种原子更新字段类(IntegerFieldUpdater、LongFieldUpdater、StampedReference)
第八章 Java中的并发工具类
8.1 等待多线程完成的CountDownLatch
- p189 CountDownLatch允许一个或多个线程等待其他线程完成操作
- p190 join方法
8.2 同步屏障CyclicBarrier
- p191 让一组线程达到后被阻塞的可循环使用屏障CyclicBarrier
- p191 CyclicBarrier简介(使用方式)
- p193 CyclicBarrier的应用场景
- p195 CyclicBarrier和CountDownLatch的区别
- p195 CyclicBarrier的其他有用的方法(reset、isBroken、getNumberWaiting)
8.3 控制并发线程数的Semaphore
- P196 信号量Semaphore
- p196 Semaphore的应用场景
- p197 Semaphore的其他方法
8.4 线程间交换数据的Exchanger
- p198 交换者Exchanger
第九章 Java中的线程池
- p200 线程池带来的三个好处
9.1 线程池的实现原理
- p200 线程池的处理流程
- p201 ThreadPoolExecutor执行execute方法的四种情况
9.2 线程池的使用
- p203 线程池的创建和构造参数介绍
- p204 四种队列和线程池都满了时的饱和策略
- p205 向线程池提交任务
- p205 关闭线程池
- p206 合理配置线程池
- p206 线程池的监控
第十章 Executor框架
- p208 Java线程的执行机制由Executor框架提供
10.1 Executor框架的两级调度模型
- p208 Executor的两级调度模型
- p208 Executor框架的结构与成员
- p209 Executor框架的结构
- p210 Executor框架的类与接口示意图
- p210 Executor框架的使用示意图
- p210 Executor框架使用流程
- p211 Executor框架的成员
- p211 ThreadPoolExecutor介绍(FixedThreadPool、SingleThreadExecutor、CachedThreadPool)
- p211 ScheduledThreadPoolExecutor介绍(ScheduledThreadPoolExecutor、SingleThreadScheduledExecutor)
- p212 Future接口
- p212 Runnable接口和Callable接口
- p212 把Runnable对象包装为Callable对象
10.2 ThreadPoolExecutor详解
- p213 FixedThreadPool详解
- p214 使用无界队列作为工作队列对线程池产生的影响
- p214 SingleThreadExecutor详解
- p215 CachedThreadPool详解
10.3 ScheduledThreadPoolExecutor详解
- p217 ScheduledThreadPoolExecutor的运行机制
- p217 ScheduledThreadPoolExecutor的执行
- p218 ScheduledThreadPoolExecutor相比ThreadPoolExecutor做的三个修改
- p218 ScheduledThreadPoolExecutor的实现
- p218 ScheduledFutureTask的三个成员变量(time、sequenceNumber、period)
- p218 ScheduledThreadPoolExecutor中线程执行任务的步骤
- P220 DelayQueue获取任务的三大步骤
- P221 DelayQueue添加任务的三大步骤
10.4 FutureTask详解
- p222 FutureTask简介
- p222 FutureTask的三种状态
- p222 FutureTask的使用
- p224 FutureTask的实现
- p227 级联唤醒