协程是什么?
协程是轻量级线程
- 非抢占式多任务处理,由协程主动交出控制权
非抢占式
:计算机资源是由CPU控制调度,程序的执行由CPU控制,一个执行中的程序时间到了或者进行了I/O等阻塞操作系统会挂起该程序等待下一个时间分片再执行 - 编译器/解释器/虚拟机层面的多任务—操作系统层面只有线程它还没有协程
- 一个线程可有
一个
goroutine或者多个
goroutine,这有GO的调度器决定。同时要记住一核一线程
如何定义Go协程
任何函数只需加上go
5个线程同时执行
func main() {
for i := 0; i < 5; i++ {
go func(i int) {
for {
fmt.Printf("Hello from "+ //printf是一个IO会交出控制权
"goroutine %d\n", i)
}
}(i)
}
time.Sleep(time.Minute) //这里是为了防止main函数结束,线程还没启动就结束了
}
错误的使用,没有交出控制权
func main() {
var a [10] int
for i := 0; i < 5; i++ {
go func(i int) {
for {
a[i]++
}
}(i)
}
time.Sleep(time.Minute) //这里是为了防止main函数结束,线程还没启动就结束了
}
GO的调度器
调度器在合适的点对协程进行切换
goroutine切换点
- I/O
I/O:指计算机的Input/Output(输入和输出) 例如:打印prinft - select
- channel
- 等待锁
- 函数调用(有时)
- runtime.Gosched()
手动交出控制器
仅供参考:不能保证切换,不能保证其他地方不切换
tips:使用-race来检测数据访问冲突