第九章 goroutine
发布时间:2021-07-06 06:55:48 所属栏目:大数据 来源: https://www.jb51.cc
导读:@H_404_0@接下来学习并发编程,并发编程是go语言最有特色的地方,go对并发编程是原生支持. @H_404_0@goroutine是go中最近本的执行单元 @H_404_0@每一个go程序至少有一个goroutine,那就是主goroutine. 当程序启动时,他会自动创建. 也就是main方法 @H_404_0@main
@H_404_0@接下来学习并发编程,并发编程是go语言最有特色的地方,go对并发编程是原生支持.
@H_404_0@goroutine是go中最近本的执行单元
@H_404_0@每一个go程序至少有一个goroutine,那就是主goroutine. 当程序启动时,他会自动创建. 也就是main方法
@H_404_0@main方法也是一个goroutine
@H_404_0@?
一. 如何定义一个协程.?package main import ( "fmt" time" ) func main() { for i := 0; i<1000; i++ { go func(i int) { for { fmt.Printf("goroutine: %d n",i) } }(i) } time.Sleep(time.Second) }
二. 对goroutine的理解@H_404_0@goroutine和Coroutine比较相似,Coroutine是协程. 其他语言都有这个叫法,但不是所有语言都支持.
1. 非抢占式多任务处理@H_404_0@var a [10]int 10; i++ { go func(i int) { for { a[i] ++ } }(i) } time.Sleep(time.Second) fmt.Println(a) }@H_404_0@猜一下,这段代码的运行结果. 结合非抢占式多任务处理 @H_404_0@结果是: 这段代码是一个死循环. 当第一次进入到循环体以后. 由于goroutine是非抢占式,所以第一次循环一直持有,没有主动释放. 所以,这段代码的结果是死循环 @H_404_0@? 2. 手动交出控制权runtime.Gosched()@H_404_0@这样就可以手动交出控制权,让其他协程运行 @H_404_0@? 3. race condition 数据访问冲突@H_404_0@如果我们在协程中没有传变量i会怎么样呢? @H_404_0@go run -race goroutine.go@H_404_0@ runtime0; i < { go func() { for { a[i] ++ runtime.Gosched() } }() } time.Sleep(time.Second) fmt.Println(a) }@H_404_0@程序启动的时候都做了哪些事? @H_404_0@首先. 开了10个协程. i从1遍历到10,发现10 < 10,for循环退出了. 但是,由于协程里面的i是直接饮用的外部的i. 当for循环完成以后,i的值变成10了. 协程里对a[10]进行++,那自然就会报异常了.? @H_404_0@所以,为了安全起见,我们把每一次开协程的时候,把i带过去. @H_404_0@修改后的 func main() { go func(i int) { for { a[i] ++ runtime.Gosched() } }(i) } time.Sleep(time.Second) fmt.Println(a) }@H_404_0@这时候我们在-race一下,查看是否还有数据访问冲突? @H_404_0@? 4. 子程序是协程的一个特例@H_404_0@普通函数和协程的区别@H_404_0@5. go语言的协程@H_404_0@6. 协程的定义@H_404_0@7. goroutine可能切换的点@H_404_0@8. 观察启动1000个协程,我们的系统分配了多少个线程.0; i < 1000; i++ { fmt.Printf(hello goroutine: %d n,i) } }(i) } time.Sleep(time.Minute) }@H_404_0@上面这段程序,看重点 @H_404_0@ 1) 开了1000个协程 @H_404_0@ 2) 主线程等待1分钟 @H_404_0@? @H_404_0@我们top一下,看看效果 @H_404_0@ (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |