Go goroutine
Posted ycx95
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go goroutine相关的知识,希望对你有一定的参考价值。
2018-07-25 16:40:10
goroutine
Go语言协程
定义
任何函数只需要加上go就能送给调度器运行
不需要在定义时区分是否是异步函数(这点是针对Python3.5引入的async def定义时说明自己是一个协程)
调度器在合适的点进行切换(非抢占式的,但切换点也不是任意的点,传统是需要显示写出来,goroutine不需要)
可能切换的点:I/O,select ; channel ;等待锁;函数调用(有时);runtime.Gosched()
注意:以上只是参考,不能保证切换,不能保证在其他地方不切换
使用-race来检测数据访问冲突
代码
goroutine.go
package main import ( "fmt" "time" ) //注意:两个i都是i没关系的 其余语言10/100个并发执行可以,但是1000个就很难啦 func main() { for i := 0; i < 1000; i++ { go func(i int) { //开goroutine 这里写成一个匿名函数要方便点 for { fmt.Printf("Hello from goroutine %d ", i) //Printf是一个io操作 由协程之间切换 } }(i) } time.Sleep(time.Minute)//如果没有这句话 是没有输出的 因为开了1000个goroutine还没来得及输出就完了 }
查看系统究竟起了多少个线程?
top命令查看:CPU 占用率 #TH线程(根据系统核来)
Coroutine协程
子程序是协程的一个特例
协程特点:
轻量级”线程”
非抢占式多任务处理,由协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
多个协程可在一个或多个线程在工作
func main() { var a [10]int
for i := 0; i<10 ; i++ {
go func(i int) { //没有i race condition
for{
a[i]++ //每个人都不断的去做加法 没有协程之间切换 没办法交出控制权
runtime.Gosched() //手动交出控制权 一般很少用 如果没有这句,该例子程序会陷入死循环
}
}(i) //没有i 会报错 index out of range
}
time.Sleep(time.Millisecond)
fmt.Println(a)
}
普通函数与协程对比:doWork做完了才把控制权交给main
其他语言对协程支持
Go语言原生支持
C++:通过Boost.Coroutine库支持
Java:不支持 (并不是完全不支持,有第三方的)
Python中:Python3.5以前使用yield关键字实现协程,Python3.5加入了async def 对协程原生支持
以上是关于Go goroutine的主要内容,如果未能解决你的问题,请参考以下文章