轻量级 “线程”!
非抢占式多任务处理,由协程主动交出控制权!
抢占式:是有操作系统主动切换线程执行
非抢占式:是由我协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
多个协程可能在一个或多个线程上运行!
检测数据冲突
go run -race xxxxx.go
goroutne 之间可以用 channel 管道进行交流沟通!
goroutine的定义
任何函数只需要加上 go 就能送给调度器运行
不需要再定义时区分是否是异步函数
调度器在合适的点进行切换(这个点不好把控)
goroutine 可能的切换点
在 I/O, SELECT
channel
等待锁
函数调用时(有时)
runtime.Gosched()
go 协程例子
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i< 10; i++ {
go func(j int) {
for {
// 这里是 fmt.Printf 打印,是一个IO的操作,涉及到IO操作是要进行切换的!
fmt.Printf("开始打印!%d\n", j)
}
}(i)
}
// 睡眠一段时间
time.Sleep(time.Millisecond)
}
func printArr(){
var a [10]int
for i := 0; i< 10; i++ {
go func(j int) {
for {
// 这个时候其他的协程是无法进行执行的
// 因为我这个进来的协程,没有办法交出控制权
// 比如我可以执行完某个打印操作,我就把控制权交出去
// 但是在这里是一个死循环,所有没有结束的地方,所有无法交出控制权
a[i]++
// 手动交出控制权
// runtime.Gosched()
}
}(i)
}
// 睡眠一段时间
time.Sleep(time.Millisecond)
fmt.Println(a)
}
func printArrTest(){
var a [10]int
for i := 0; i< 10; i++ {
// 这里没有像上面那样通过这里传入数据
// 就表示这个 func 是使用上面循环的 i 参数,这样就形成了一个闭包
// 当 i = 10的时候,已经进不去循环了,但是我里面使用的还是 for 循环的 i,
// 所以我里面闭包使用的 i 始终是同一个 i,当 i = 10 的时候,我里面正好 a 数组没有下坐标为 10的位置,所以就报错
go func() { // 所以推荐通过,这里传入参数,就像上面的那个例子一样
for {
// 这个时候其他的协程是无法进行执行的
// 因为我这个进来的协程,没有办法交出控制权
// 比如我可以执行完某个打印操作,我就把控制权交出去
// 但是在这里是一个死循环,所有没有结束的地方,所有无法交出控制权
a[i]++
// 手动交出控制权
// runtime.Gosched()
}
}()
}
// 睡眠一段时间
time.Sleep(time.Millisecond)
fmt.Println(a)
}
有疑问加站长微信联系(非本文作者)