并发模型-CSP¶
Communicating Sequential Processes
通信顺序进程,又翻译为交换消息的顺序程序,用来描述并发性系统的交互模式
早在上个世纪七十年代,多核处理器还是一个科研主题,并没有进入普通程序员的视野。 Tony Hoare 于 1977 年提出通信顺序进程(CSP)理论,遥遥领先与他所在的时代。
CSP有以下三个特点:
1.每个程序是为了顺序执行而创建的
2.数据通过管道来通信,而不是通过共享内存
3.通过增加相同的程序来扩容
// Golang的并发模型基于CSP理论,Golang并发的口号是:不用通过共享内存来通信,而是通过通信来共享内存
Golang并发模式支持并发的元素集:
goroutines
channels
select
sync package
// 其中goroutines,channels和select 对应于实现CSP理论,即通过通信来共享内存
// 这几乎能解决Golang并发的90%问题,另外的10%场景需要通过同步原语来解决,即sync包相关的结构
实现-GPM调试模型¶
GPM 代表了三个角色,分别是:
1. Goroutine:
用 go 关键字创建的执行体,它对应一个结构体 g,结构体里保存了 goroutine 的堆栈信息
2. Processor
表示处理器,有了它才能建立 G、M 的联系
3. Machine
表示操作系统的线程
Goroutine:
Goroutine 就是代码中使用 go 关键词创建的执行单元,也是大家熟知的有 “轻量级线程” 之称的协程,
协程是不为操作系统所知的,它由编程语言层面实现,上下文切换不需要经过内核态,
再加上协程占用的内存空间极小,所以有着非常大的发展潜力。
Proccessor:
负责 Machine 与 Goroutine 的连接,它能提供线程需要的上下文环境,也能分配 G 到它应该去的线程上执行
处理器的数量也是默认按照 GOMAXPROCS 来设置的,与线程的数量一一对应
Machine:
M 就是对应操作系统的线程,最多会有 GOMAXPROCS 个活跃线程能够正常运行,
默认情况下 GOMAXPROCS 被设置为内核数,假如有四个内核,那么默认就创建四个线程,
每一个线程对应一个 runtime.m 结构体。
线程数等于 CPU 数的原因是:
每个线程分配到一个 CPU 上就不至于出现线程的上下文切换,可以保证系统开销降到最低
M 里面存了两个比较重要的东西,一个是 g0,一个是 curg:
g0:会深度参与运行时的调度过程,比如 goroutine 的创建、内存分配等
curg:代表当前正在线程上执行的 goroutine。
参考¶
[掘金]Go 语言的 GPM 调度器是什么?: https://juejin.cn/post/6844904130398404616