基本概念

  • 并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。这种方式我们称之为并发(Concurrent)。

  • 并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行。这种方式我们称之为并行(Parallel)。

并发目的

由于CPU和I/O天然存在的矛盾,传统顺序的同步工作模式导致任务阻塞,CPU处于空闲状态,浪费资源。多线程为了突破同步工作模式的情况下CPU资源的浪费,即使单核情况下也能将时间片拆分成单位给更多的线程来轮询使用。多线程在不同享状态的情况下非常高效,不管协同式还是抢占式都能在单位时间内执行更多的任务,从而更好地榨取CPU资源。因此,并发的目的就是为了提供程序运行的性能。

并发技术

多线程

为了能够充分利用CPU资源,需要采用多线程机制,在CPU上进行调度。何为线程?是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

线程交互

  • 交互方式:线程交互也就是线程直接的通信,最直接的办法就是线程直接通信传值,而间接方式则是通过共享变量来达到彼此的交互。如:等待、通知、中断、织入。
  • 线程安全:我们最关注的还是通过共享变量来达到交互的方式。如果线程执行的任务相互独立则不存在安全问题,但多数情况下线程直接需要打交道,而且需要分享共享资源,那么这个时候最核心的就是线程安全。

性能优化

常见的性能指标包括:QPSTPSRT。这里不考虑外部网络、分布式架构、各级缓存、数据冗余等设计,主要针对单节点的性能优化。

随着用户激增,请求次数的增加,服务也对应着需要并发模型来支撑。但是一个节点的并发量有个上限,当达到这个上限后,响应时间就会变长,所以我们需要探索并发到什么程度才是最优的,才能保证最高的并发数,同时响应时间又能保持在理想情况

服务接收到一个请求后,主要经历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上不去。大部分情况跟共享资源的使用有关,即锁的使用需要优化

并发模型

采用多线程方式实现并发,需要合理使用各种锁。除了使用多线程,下面介绍两类并发模型流水线模型和函数式模型。

  • 流水线模型:总体的思想就是纵向切分任务,把任务里面耗时过久的环节单独隔离出来,避免完成一个任务需要耗费等待的时间。在实现上又分为ActorsChannels模型。比如基于JavaAkka/Reator或者golang就是为流水线模式而生的并发语言,还有nodeJS等等。
  • 函数式模型:类似流水线模型,单一的函数是无状态的,所以避免了资源竞争的复杂度,同时每个函数类似流水线里面的单一环境,彼此直接通过函数调用传递参数副本,函数之外的数据不会被修改。函数式模式跟流水线模式相辅相成逐渐成为更为主流的并发架构。

java并发体系

java中主要以多线程方式实现并发,主要内容有:

  • 并发基础:
    • AQS:
      1. AbstractqueuedSynchronizer同步器
      2. CLH同步队列
      3. 同步状态的获取和释放
      4. 线程阻塞和唤醒
    • CAS: Compare and Swap 缺陷
  • Java内存模型JMM:线程通信、消息传递
  • 内存模型:
    • 重排序
    • 顺序一致性
    • happens-before
    • as if serial
  • synchronized:
    • 同步、重量级锁、synchronized原理
    • 锁优化:
      1. 自旋锁
      2. 轻量级锁
      3. 重量级锁
      4. 偏向锁
  • 原子操作:
    • 基本类型:AtomicBooleanAtomicIntegerAtomicLong
    • 数组:AtomicIntegerArrayAtomicLongArrayAtomicReferenceArray
    • 引用类型:AtomicReferenceAtomicReferenceArrayFieldUpdater
  • 线程池:
    • ThreadPoolExecutor(拒绝策略、参数优化)、ScheduledExecutorService
    • CallableFuture
  • 并发集合:ConcurrentHashMapCopyOnWriteArrayListConcurrentLinkedQueueBlockingQueueConcurrentSkipListMap
  • 并发工具类:SemaphoreCyclicBarrierCountDownLatch
  • 锁:ReentrantLockConditionReentrantReadWriteLockLockSupport
  • volatile:
    • volatile实现机制
    • 内存语义
    • 内存模型
  • 其他:
    • ThreadLocal
    • Fork/Join

相关资料

  • 《Java并发编程实战》Doug Lea
  • 《Java并发编程的艺术》讲解并发包内部实现原理
  • 《Java多线程编程核心技术》高洪沿
  • 《图解Java多线程设计模式》并发编程设计模式方面的经典书籍
  • 《操作系统:精髓与设计原理》经典操作系统教材
  • http://ifeve.com 国内专业并发编程网站
  • http://www.cs.umd.edu/~pugh/java/memoryModel/
  • 多线程小抄集 (公众号:朱小厮的博客)
  • 高并发知识体系 (公众号:云时代架构)