持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
进程、线程、协程
进程和线程
- 进程:程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位
- 线程:是进程的一个执行实体,是CPU调度和分派的基本单位,比进程小能独立运行的基本单位
- 一个进程可以创建和撤销多个线程,同一个进程中的多个线程可以并发执行
进程和协程
-
协程:由用户的程序调度的,系统不知道协程的存在。独立的栈空间,共享堆空间。
- 内存消耗远比 JAVA、C的线程少
- 切换协程是开销远比线程小
- 仅3个寄存器修改
-
线程:一个线程上可以跑多个协程,协程是轻量级的线程。
- 内存消耗大概 8M
- 切换线程涉及模式切换(用户态切换内核态)、16个寄存器刷新
协程是 go语言中提出的概念,本质上就是 goroutine。所以,Go语言上支持协程的调度,封装了对 goroutine 的调度和处理。如长时间执行或系统调用时,主动将当前 goroutine 的CPU 转让出去。
协程应用
在一个函数调用前加上go关键字,这次调用就会在一个新的goroutine中并发执行。当被调用的函数返回时,这个goroutine也自动结束。
func hello() {
fmt.Println("Hello Goroutine!")
}
func main() {
go hello()
fmt.Println("main goroutine done!")
}
所以,执行以上代码时,你会发现只打印 main goroutine done!.并没有打印Hello Goroutine! 因为main函数执行完之后goroutine也结束了。启动的hello 时异步并行的,main函数结束goroutine就会一同结束。所以可能hello 函数还没执行完,整个main 就结束了导致就没有输出hello函数的结果。
并发模型的通信 Channel
启动多个goroutine 后,每个goroutine 之间如何通信?
共享内存方式:使用go的 消息机制 channel 。channel 是 Go 语言在语言级别提供的 goroutine 间的通信方式。
channel的声明。使用关键字 chan。一个 channel 只能传递一种类型的值,这个类型需要在声明 channel 时指定。
var chanName chan ElementType
var ch1 chan int
var ch2 chan bool
声明一个 channel 需要使用 make 函数初始化之后才可以使用。如上如过声明后,零值是空值 nil。
ch := make(chan int)
// 写入
ch <- value
// 读出
value := <- ch
// 关闭
close(ch)
对一个 channel 写入数据就需要读出,如果一直都不读出将导致堵塞。关闭 channel 时,需要通知接收方goroutine所有的数据都发送完毕的时候才需要关闭通道。
参考资料: