这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
掌握
- 并发编程
不足
- 依赖管理没掌握
- 单元测试一直懵
并发模型
Go 语言的并发模型其中一种是 Goroutine,他是Go中最基本的执行单元。事实上每一个Go程序至少有一个Goroutine:主Goroutine。当程序启动时,它会自动创建。
- 先简单理解一下线程和协程的区别
线程(Thread) :用户态,轻量级线程,栈MB级别。
协程(coroutine) :内核态,线程跑多个协程,栈KB级别
协程和线程类似,共享堆,不共享栈,协程的切换一般由程序员在代码中显式控制。它避免了上下文切换的额外耗费,兼顾了多线程的优点,简化了高并发程序的复杂。
Goroutine和其他语言的协程(coroutine)在使用方式上类似,但从字面意义上来看不同(一个是Goroutine,一个是coroutine),再就是协程是一种协作任务控制机制,在最简单的意义上,协程不是并发的,而Goroutine支持并发的。因此Goroutine可以理解为一种Go语言的协程,同时它可以运行在一个或多个线程上。1. 线程都有一个独立的 ID 号,而 goroutine 却没有。
事实上,Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数创建一个默认的 goroutine。
简单实例:
func loop() {
for i := 0; i < ; i++ {
fmt.Printf("%d ", i)
}
}
func main() {
go loop() // 启动一个goroutine
loop()
}
另外,goroutine 调度器使用 GOMAXPROCS 参数来控制会有多少个 OS 的线程同时执行 Go 的代码。
Go 语言的并发模型还有一种,是Go语言特有的,也是Go语言推荐的:CSP(communicating sequential processes)并发模型。Go的CSP并发模型,是通过goroutine和channel来实现的。
goroutine是Go语言中并发的执行单位。有点抽象,其实就是和传统概念上的”线程“类似,可以理解为”线程“。channel是Go语言中各个并发结构体(goroutine)之前的通信机制。 通俗的讲,就是各个 goroutine 之间通信的”管道“,有点类似于Linux中的管道。
生成一个goroutine的方式:Go一下。
go f();
通信机制 channel 也很方便,传数据用 channel <- data ,取数据用 <-channel 。
在通信过程中,传数据 channel <- data 和取数据 <-channel 必然会成对出现,因为这边传,那边取,两个 goroutine 之间才会实现通信。
而且不管传还是取,必阻塞,直到另外的 goroutine 传或者取为止。