goroutine
goroutine是Go并行设计的核心。goroutine说到底其实就是协程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。也正因为如此,可同时运行成千上万个并发任务。goroutine比thread更易用、更高效、更轻便。
协程的特点
- 协程是一个轻量级的线程,此处可以与进程、线程、协程 进行对比
- Go协程是非抢占式多任务处理,需要由协程主动交出控制权
- 协程是一个 虚拟机层面的多任务处理
- 多个协程可能运行在一个或者多个线程上
创建 goroutine
- 在函数前 加 go 关键字 即可创建 goruoutine
func newTask() {
for {
fmt.Println("this is new task")
time.Sleep(time.Second) //延时1s
}
}
func main() {
go newTask() //❤️建一个协程,新建一个任务
for {
fmt.Println("this is a main goroutine")
time.Sleep(time.Second) //延时1s
}
}
主协程先退出,其它子协程夜会跟着退出
// 主协程退出了,其它子协程也要跟着退出
// manin 函数本身是一个 goroutine
func main() {
go func() {
fmt.Println("this is a new task")
time.Sleep(time.Second)
}() //() 代表调用
i :=0
for {
i++
fmt.Println("main this is a main task i=", i)
time.Sleep(time.Second)
if i == 3 {
break
}
}
}
Go语言协程调度器
Go语言中所有的协程都通过调度器进行调度,大并发下成百上千甚至几千的协程调用 通过调度器安排到不同的线程中执行。
调度的切换调度器会在何时的时间点进行协程之间的切换,通过切换可以将计算资源分配给其他协程而不至于被一个协程锁死资源
- goroutine 可能的切换点 仅是参考 不能保证切换,不能保证在其他地方不进行切换
- IO/SELECT
- channel
- 函数调用 (有时)
- runtime.Gosched() 手动切换
- 等待锁
相关方法
runtime.Gosched()
让出时间片,先让别的协程执行,它执行完,在回来执行此协程runtime.Goexit()
终止所在的协程runtime.GOMAXPROCS()
指定以x核运算