Go的CSP并发模型

Communicating Sequential Processes

Posted by 大攀 on Friday, November 27, 2020

TOC

CSP并发模型

  独立的并发实体(Process)通过共享通讯管道(Channel)进行通讯的并发模型。CSP中channel是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的channel。 Process 可以订阅任意个 Channel,Channel 也并不关心是哪个 Process 在利用它进行通信;Process 围绕 Channel 进行读写,形成一套有序阻塞和可预测的并发模型。

  Go 语言实现了 CSP 部分理论,goroutine 对应 CSP 中并发执行的实体,channel 也就对应着 CSP 中的 channel。

Goroutine和Channel

  Goroutine协程是一种轻量线程,它不是操作系统的线程,而是将一个操作系统线程分段使用,通过调度器实现协作式调度(类似coroutine)。

将一个线程分为“用户态”和“内核态”线程,一个“用户态线程”必须绑定一个“内核态线程”,但是CPU并不知道有“用户态线程”的存在,它只知道运行的是一个“内核态线程”(Linux的PCB进程控制块)。 再细化分类,内核线程依然叫“线程(thread)”,用户线程叫“协程(co-routine)”,一个或多个协程(co-routine)绑定一个或多个线程(thread),GPM即为M:N调度关系。

  Channel类似Unix的Pipe,用于协程之间通讯和同步。协程之间虽然解耦,但是它们和Channel有着耦合。

coroutine与goroutine

coroutine是一种运行在用户态的用户线程,go底层选择使用coroutine的出发点是因为,它具有以下特点:

  • 用户空间,避免了内核态和用户态的切换成本。
  • 可以由语言和框架层进行调度。
  • 更小的栈空间允许创建大量的实例。

goroutine与coroutine异同:

  • goroutine 和 coroutine 的概念和运行机制都是脱胎于早期的操作系统(划分用户态空间,并在此空间进行调度)。
  • goroutine 占用内存更小且可伸缩(可大量创建)
  • goroutine 调度更灵活(runtime调度)
  • 指定多个P,goroutine 可以发生并行执行(coroutine 始终顺序执行)
  • goroutines 通过通道(channel)来通信,coroutine 通过让出和恢复(yield和resume)操作来通信
  • goroutine 抢占式任务处理。可以发生在多线程环境下,goroutine 无法控制自己获取高优先度支持;coroutine 协作式任务处理。始终发生在单线程,coroutine 程序需要主动交出控制权,宿主才能获得控制权并将控制权交给其他 coroutine。

comments powered by Disqus