Java并发编程知识体系概览
基本概念
并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。这种方式我们称之为并发(Concurrent)。
并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行。这种方式我们称之为并行(Parallel)。
并发目的
由于CPU和I/O天然存在的矛盾,传统顺序的同步工作模式导致任务阻塞,CPU处于空闲状态,浪费资源。多线程为了突破同步工作模式的情况下CPU资源的浪费,即使单核情况下也能将时间片拆分成单位给更多的线程来轮询使用。多线程在不同享状态的情况下非常高效,不管协同式还是抢占式都能在单位时间内执行更多的任务,从而更好地榨取CPU资源。因此,并发的目的就是为了提供程序运行的性能。
并发技术
多线程
为了能够充分利用CPU资源,需要采用多线程机制,在CPU上进行调度。何为线程?是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
线程交互
- 交互方式:线程交互也就是线程直接的通信,最直接的办法就是线程直接通信传值,而间接方式则是通过共享变量来达到彼此的交互。如:等待、通知、中断、织入。
- 线程安全:我们最关注的还是通过共享变量来达到交互的方式。如果线程执行的任务相互独立则不存在安全问题,但多数情况下线程直接需要打交道,而且需要分享共享资源,那么这个时候最核心的就是线程安全。
性能优化
常见的性能指标包括:QPS
、TPS
、RT
。这里不考虑外部网络、分布式架构、各级缓存、数据冗余等设计,主要针对单节点的性能优化。
随着用户激增,请求次数的增加,服务也对应着需要并发模型来支撑。但是一个节点的并发量有个上限,当达到这个上限后,响应时间就会变长,所以我们需要探索并发到什么程度才是最优的,才能保证最高的并发数,同时响应时间又能保持在理想情况。
服务接收到一个请求后,主要经历CPU等待、执行和IO等待、读写的时间。
单线程
RT = T(cpu) + T(io)
QPS = 1000ms / RT
多线程
cpu核数为M,利用率为P。最优并发数N = [T(cpu) + T(io)] / T(cpu) * M * P
QPS = 1000ms / RT * N
QPS = 1000ms / [T(cpu) + T(io)] * [T(cpu) + T(io)] / T(cpu) * M * P
QPS = 1000ms / T(cpu) * M * P
在M固定的情况下,如果cpu利用率负载不高,利用率p上不去。大部分情况跟共享资源的使用有关,即锁的使用需要优化。
并发模型
采用多线程方式实现并发,需要合理使用各种锁。除了使用多线程,下面介绍两类并发模型流水线模型和函数式模型。
- 流水线模型:总体的思想就是纵向切分任务,把任务里面耗时过久的环节单独隔离出来,避免完成一个任务需要耗费等待的时间。在实现上又分为
Actors
和Channels
模型。比如基于Java
的Akka
/Reator
或者golang
就是为流水线模式而生的并发语言,还有nodeJS
等等。 - 函数式模型:类似流水线模型,单一的函数是无状态的,所以避免了资源竞争的复杂度,同时每个函数类似流水线里面的单一环境,彼此直接通过函数调用传递参数副本,函数之外的数据不会被修改。函数式模式跟流水线模式相辅相成逐渐成为更为主流的并发架构。
java并发体系
java中主要以多线程方式实现并发,主要内容有:
- 并发基础:
- AQS:
- AbstractqueuedSynchronizer同步器
- CLH同步队列
- 同步状态的获取和释放
- 线程阻塞和唤醒
- CAS: Compare and Swap 缺陷
- AQS:
- Java内存模型JMM:线程通信、消息传递
- 内存模型:
- 重排序
- 顺序一致性
- happens-before
- as if serial
- synchronized:
- 同步、重量级锁、
synchronized
原理 - 锁优化:
- 自旋锁
- 轻量级锁
- 重量级锁
- 偏向锁
- 同步、重量级锁、
- 原子操作:
- 基本类型:
AtomicBoolean
、AtomicInteger
、AtomicLong
- 数组:
AtomicIntegerArray
、AtomicLongArray
、AtomicReferenceArray
- 引用类型:
AtomicReference
、AtomicReferenceArrayFieldUpdater
- 基本类型:
- 线程池:
ThreadPoolExecutor
(拒绝策略、参数优化)、ScheduledExecutorService
Callable
和Future
- 并发集合:
ConcurrentHashMap
、CopyOnWriteArrayList
、ConcurrentLinkedQueue
、BlockingQueue
、ConcurrentSkipListMap
等 - 并发工具类:
Semaphore
、CyclicBarrier
、CountDownLatch
- 锁:
ReentrantLock
、Condition
、ReentrantReadWriteLock
、LockSupport
- volatile:
volatile
实现机制- 内存语义
- 内存模型
- 其他:
ThreadLocal
Fork/Join
相关资料
- 《Java并发编程实战》Doug Lea
- 《Java并发编程的艺术》讲解并发包内部实现原理
- 《Java多线程编程核心技术》高洪沿
- 《图解Java多线程设计模式》并发编程设计模式方面的经典书籍
- 《操作系统:精髓与设计原理》经典操作系统教材
- http://ifeve.com 国内专业并发编程网站
- http://www.cs.umd.edu/~pugh/java/memoryModel/
- 多线程小抄集 (公众号:朱小厮的博客)
- 高并发知识体系 (公众号:云时代架构)