这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
进程
进程可以简单来说是正在进行的一个过程或者说一个任务。程强调的是动态性,CPU会不断访问内存,执行进程的指令,完成进程的所提出的任务。
程序从外存(可以理解为硬盘)被载入到内存之后,它会被划分为 程序段和数据段。
操作系统(OS)通过进程控制块(Process Control Block,PCB) 存放进程的程序段和数据段的位置。
注意:PCB 是进程存在的唯一标志。
进程是程序在系统执行的基本实体,程序只是进程的一部分
进程实体 = PCB + 程序段 + 数据段
进程是进程实体的运行过程,是系统进行分配、调度及执行的一个独立单元。
严格来说,进程实体和进程并不一样,进程实体是静态的,而进程是动态的(程强调的是动态性)
线程与协程的区别
线程:内核态,是比进程更小粒度的运行单位,需要OS来调度,内存消耗是MB级别。
协程:用户态,是比线程更小的粒度,通过m:n的比例在一个线程中再细分出来的单位,用户可以自由调度,内存消耗是KB级别。
协程对比线程的优势:
- 存在于用户态,可操作性强,调度可由自己控制。
- 更轻量,所需资源更少。
Goroutine
Go语言的Go关键字跑的就是协程,称为goroutine。
它的核心是MPG调度模型:
- M:内核线程
- P:处理器,用来执行 goroutine,它维护了本地可运行队列
- G:goroutine,代码和数据结构
- S:调度器,维护M和P的信息
package main
import (
"fmt"
"sync"
)
func hello(i int) {
println("hello : " + fmt.Sprint(i))
}
func main() {
go func(j int) {
hello(j)
}(i)
}
并发的通信 (通信顺序进程CSP)
并发程序之间的通信,一般都是通过共享内存的形式实现通信,临界区一般需要加锁保护。
但是,Go语言采取的是 通信共享内存,这个过程是反过来的,但用起来更为直观。