第 1章 线程机制 1
1.1 线程是什么 1
1.2 线程的映射 3
1.2.1 多对一映射 4
1.2.2 一对一映射 4
1.2.3 多对多映射 5
1.2.4 Java层到内核层 6
1.3 Java线程的状态 7
1.4 Java线程的调度 10
1.5 Java线程的优先级与执行机制 11
1.6 Java线程的CPU时间 14
1.7 Java线程的yield操作 15
1.8 Java线程的sleep操作 17
1.9 Java线程的Interrupt操作 20
1.9.1 可运行状态的中断 23
1.9.2 阻塞/等待状态的中断 23
1.9.3 经典中断实现方式 24
1.9.4 park的特殊中断 26
1.10 Java线程的阻塞与唤醒 26
1.11 Java线程的join操作 34
第 2章 线程I/O模型 38
2.1 线程与阻塞I/O 38
2.1.1 单线程阻塞I/O模型 39
2.1.2 多线程阻塞I/O模型 40
2.2 线程与非阻塞I/O模型 41
2.2.1 应用层I/O多路复用 43
2.2.2 内核I/O多路复用 43
2.2.3 内核回调事件驱动I/O 44
2.3 Java多线程非阻塞I/O模型 46
2.4 多线程带来了什么 48
2.4.1 提升执行效率 49
2.4.2 提升用户体验 50
2.4.3 让编码更难 50
2.4.4 资源开销与上下文切换开销 51
第3章 Java内存模型 53
3.1 计算机的运行 53
3.2 Java内存模型 56
3.3 volatile能否保证线程安全 59
3.4 happens-before原则 62
3.4.1 单线程原则 65
3.4.2 锁原则 66
3.4.3 volatile原则 67
3.4.4 线程start原则 67
3.4.5 线程join原则 68
3.4.6 线程interrupt原则 68
3.4.7 finalize原则 69
3.4.8 传递原则 70
3.5 Java指令重排 70
第4章 并发知识 75
4.1 synchronized互斥锁 75
4.1.1 作用在对象方法上 76
4.1.2 作用在类静态方法上 79
4.1.3 作用在对象方法里面 80
4.1.4 作用在类静态方法里面 81
4.2 乐观的并发策略 85
4.3 自旋锁 87
4.3.1 UMA架构与NUMA架构 88
4.3.2 原始自旋锁 90
4.3.3 排队自旋锁 91
4.3.4 CLH锁 93
4.3.5 MCS锁 95
4.4 线程饥饿 97
4.4.1 synchronized饥饿 97
4.4.2 优先级饥饿 99
4.4.3 线程自旋饥饿 100
4.4.4 等待唤醒饥饿 101
4.4.5 公平性解决饥饿 102
4.5 数据竞争 104
4.6 竞争条件 108
4.6.1 线程执行顺序的不确定性 110
4.6.2 并发机制 111
4.7 死锁 113
4.7.1 锁的顺序化 116
4.7.2 资源合并 116
4.7.3 避免锁嵌套 117
4.7.4 锁超时机制 117
4.7.5 抢占资源机制 118
4.7.6 撤销线程机制 118
4.7.7 死锁的检测 119
第5章 AQS同步器 120
5.1 什么是AQS同步器 120
5.2 AQS的等待队列与状态转换 120
5.3 AQS的独占锁与共享锁 125
5.4 AQS独占锁获取与释放 127
5.4.1 获取独占锁的逻辑 128
5.4.2 尝试获取独占锁 130
5.4.3 入队操作逻辑 130
5.4.4 入队后的操作 132
5.4.5 虚节点可能消失 133
5.4.6 取消锁获取操作 134
5.4.7 唤醒后继节点 136
5.4.8 释放独占锁的逻辑 137
5.5 AQS共享锁获取与释放 138
5.5.1 获取共享锁的逻辑 138
5.5.2 入队操作 140
5.5.3 入队后的操作 140
5.5.4 引入PROPAGATE状态 143
5.5.5 释放共享锁的逻辑 146
5.6 AQS的阻塞与唤醒 146
5.6.1 许可机制 148
5.6.2 LockSupport示例 149
5.6.3 park与unpark的顺序 150
5.6.4 park对中断的响应 151
5.6.5 park是否会释放锁 152
5.6.6 LockSupport的实现 154
5.7 AQS的中断机制 156
5.7.1 synchronized不支持中断 157
5.7.2 AQS独占模式的中断 158
5.7.3 AQS共享模式的中断 160
5.8 AQS的超时机制 161
5.8.1 synchronized不支持超时 161
5.8.2 AQS独占模式的超时 162
5.8.3 AQS共享模式的超时 163
5.9 AQS的原子性如何保证 164
5.10 AQS的自旋锁 175
5.11 AQS的公平性 177
5.12 AQS的条件队列 179
5.12.1 await方法 179
5.12.2 signal方法 182
5.13 AQS自定义同步器 183
5.13.1 AQS设计思想 183
5.13.2 独占模式 184
5.13.3 共享模式 186
第6章 常见的同步器 189
6.1 常见的同步器 189
6.2 闭锁 192
6.3 信号量 197
6.3.1 非公平模式的实现 198
6.3.2 公平模式的实现 201
6.3.3 信号量的使用示例 202
6.4 循环屏障 204
6.5 相位器 210
6.5.1 相位器的主要概念及方法 211
6.5.2 相位器的3个例子 212
6.5.3 相位器的状态示意图 215
6.5.4 相位器的实现原理 216
6.6 交换器 220
6.6.1 交换器的实现原理 223
6.6.2 交换器的单槽模式 226
6.6.3 交换器的多槽模式 228
第7章 原子类 233
7.1 原子整型 233
7.1.1 一行代码等于原子性吗 233
7.1.2 volatile能保证原子性吗 234
7.1.3 synchronized能解决问题吗 235
7.1.4 AtomicInteger 237
7.1.5 实现原理 238
7.2 原子引用 239
7.3 原子数组 243
7.3.1 AtomicIntegerArray 244
7.3.2 AtomicLongArray 247
7.3.3 AtomicReferenceArray 248
7.4 原子变量更新器 249
第8章 阻塞队列 254
8.1 阻塞队列概述 254
8.2 数组阻塞队列 258
8.3 链表阻塞队列 263
8.4 优先级阻塞队列 271
8.5 延迟阻塞队列 279
8.5.1 优先级队列 281
8.5.2 DelayQueue的阻塞与唤醒 283
8.5.3 DelayQueue的实现原理 284
8.6 链表阻塞的双向队列 288
第9章 锁 298
9.1 可重入锁 298
9.1.1 非公平模式的实现 299
9.1.2 公平模式的实现 301
9.1.3 公平模式的3个示例 302
9.2 读写锁 305
9.2.1 读写锁的性质 306
9.2.2 简单的实现版本 307
9.2.3 读写锁的升级与降级 308
9.2.4 读写锁的实现思想 309
9.2.5 读写锁的共用状态变量 312
9.2.6 读写锁的公平/非公平模式 313
9.2.7 写锁的实现 314
9.2.8 读锁的实现 315
9.2.9 读写锁的使用示例 317
9.3 锁的条件机制 318
9.3.1 wait/notify模式 318
9.3.2 Condition 320
第 10章 任务执行器 322
10.1 任务执行器接口 322
10.1.1 同步执行器 322
10.1.2 一对一执行器 323
10.1.3 线程池执行器 323
10.1.4 串行执行器 325
10.2 任务执行器的ExecutorService接口 326
10.3 线程池任务执行器 331
10.3.1 线程池任务执行器的运行状态 332
10.3.2 线程池任务执行器的使用示例 334
10.3.3 线程池任务执行器的实现原理 335
第 11章 其他并发工具 344
11.1 线程本地变量 344
11.1.1 线程本地变量的使用示例 344
11.1.2 线程本地变量的3个主要方法 346
11.1.3 JDK中线程本地变量的实现思想 347
11.1.4 JDK中线程本地变量的实现源码 348
11.1.5 线程本地变量的内存泄漏 352
11.2 写时复制数组列表 353
第 12章 C++模拟实现Java线程 359
12.1 模拟实现Java线程 359
12.2 模拟实现yield语义 365
12.3 模拟实现sleep操作 367
12.4 模拟实现synchronized语义 369
12.5 模拟实现Interrupt操作 372