标签:虚拟机 work 加法 UNC 解释 运行 python3 参考 协程
2018-07-25 16:40:10
任何函数只需要加上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\n", i) //Printf是一个io操作 由协程之间切换 } }(i) } time.Sleep(time.Minute)//如果没有这句话 是没有输出的 因为开了1000个goroutine还没来得及输出就完了 }
查看系统究竟起了多少个线程?
top命令查看:CPU 占用率 #TH线程(根据系统核来)
子程序是协程的一个特例
协程特点:
轻量级”线程”
非抢占式多任务处理,由协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
多个协程可在一个或多个线程在工作
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 对协程原生支持
标签:虚拟机 work 加法 UNC 解释 运行 python3 参考 协程
原文地址:https://www.cnblogs.com/ycx95/p/9367128.html