Dan

编程笔记 - 并发

2017-04-21

并发其实是个很宏大的话题,简单来说是为了消灭等待,追求更高的处理效率。在单机场景下,并发是为了平衡CPU和内存、IO(磁盘|网络)间的速度差异。在分布式场景下,并发则是为了追求完美的分治:任务、数据切割和单个worker处理能力的平衡。
并发的问题可以分为两类:分工协作、同步互斥。同步互斥在编程笔记 - 锁已有记录,这里记录下几个分工协作的编程模型(这里请忽略并发、并行的概念差异)。

并发模型

  • 多线程:多线程模型算是最基本的并发了。记录两个比较常见的问题:
    1、进程和线程的区别。进程和线程都是操作系统的基本概念,比较喜欢这篇文章的解释。个人的理解是,CPU太快,比内存、IO快太多。所以操作系统对任务按进程划分,分时间片执行提升CPU利用率。但进程的划分太宽泛,所以每个进程内又对任务切割成多个线程执行。不管划分多少级,本质都是为了提高CPU利用率。而这些划分必然会导致有些是共享的(内存),有些又不共享,所以才会有各种协调机制来防止各级内和各级间的资源冲突。
    2、java中的多线程。
    • Thread:最直白的线程封装。
    • ExecutorService:更好用的线程池工具类。
    • ForkJoin:分治思想的一种实现(下图)。 note
  • Callback:回调函数算是开销最小的并发了,应用最多的地方是JS,node算是集大成者。优点是简单灵活,缺点是调度层可能变得复杂。

  • Actor、CSP(通信顺序进程): 二者都是通过借鉴生产者/消费者的模式解耦消息/事件的产生和处理过程。不同的地方是: 1、消息/事件的收发:Actor注重消息的处理单元(Actor),而不是消息传送方式,所以发送消息需要知道对方是谁。而CSP解耦了发送方和接收方,处理单元不需要关心消息的收发是谁。
    2、消息/事件的存储:Actor会在本地维护一个mailBox来存储消息。而CSP会类似没Q点机制,使用预先定义的Channel来存储消息。

  • 协程(微线程):简单来说,协程是比线程更轻量级的存在。进程、线程都是操作系统的基本调度单位,所以切换会带来一定的开销。而协程是用户控制的任务(函数)切换,系统开销很小。可以这样简单理解,通过生成器(比如python的yield)让函数有了多个出口,转而执行其他代码而不必引起操作系统级别的上下文切换,所以性能会更高。

Comments