并发概念程序员
Go是并发语言,而非并行语言。并发性是同时处理许多事情的能力。并行性parallelism指能够同时作不少事情。并发
Go中使用Goroutines来实现并发concurently。Goroutines是与其余函数或方法同时运行的函数或方法。异步
Goroutines被认为是轻量级的线程,与线程相比,建立Goroutines成本很小,故Go应用程序能够并发执行数千个Goroutines。async
不须要在定义时区分是不是异步函数(这点是针对Python3.5引入的async def定义时说明本身是一个协程)函数
调度器在合适的点进行切换(非抢占式的,但切换点也不是任意的点,传统是须要显示写出来,goroutine不须要)spa
可能切换的点:I/O,select ; channel ;等待锁;函数调用(有时);runtime.Gosched()线程
注意:以上只是参考,不能保证切换,不能保证在其余地方不切换设计
使用-race来检测数据访问冲突3d
任何函数或方法调用前面加上go就能送给调度器运行 ,运行一个新的Goroutine。code
例子:
goroutine.go
输出是:Hello from goroutine 随机打印的值
查看系统究竟起了多少个线程?
top命令查看:CPU 占用率 #TH线程(根据系统核来)
子程序是协程的一个特例
协程特色:
轻量级”线程”
非抢占式多任务处理,由协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
多个协程可在一个或多个线程在工做
启动多个Goroutine
例子1
func numbers() { for i := 1; i <= 5; i++ { time.Sleep(250 * time.Millisecond) fmt.Printf("%d ", i) } } func alphabets() { for i := 'a'; i <= 'e'; i++ { time.Sleep(400 * time.Millisecond) fmt.Printf("%c ", i) } } func main() { go numbers() go alphabets() time.Sleep(3000 * time.Millisecond) fmt.Println("main terminated") } 输出:1 a 2 3 b 4 c 5 d e main terminated
例子2
普通函数与协程对比:doWork作完了才把控制权交给main。
Goroutine规则:
例子:
func hello() { fmt.Println("Hello world goroutine") } func main() { go hello() //因为main进行Sleep,故go hello()有足够时间在main Goroutine终止以前执行 time.Sleep(1 * time.Second) fmt.Println("main function") } //输出是:Hello world goroutine main function
Go语言原生支持
C++:经过Boost.Coroutine库支持
Java:不支持 (并非彻底不支持,有第三方的)
Python中:Python3.5之前使用yield关键字实现协程,Python3.5加入了async def 对协程原生支持