发布时间:2023-03-06 15:30
goroutine是go的设计核心,就是协程
主协程终止了,子协程也终止
package main import ( \"fmt\" \"time\" ) func newTask() { for { fmt.Println(\"this is a newTask\") time.Sleep(time.Second) //延时1s } } func main() { go newTask() //新建一个协程, 新建一个任务 for { fmt.Println(\"this is a main goroutine\") time.Sleep(time.Second) //延时1s } }
package main import ( \"fmt\" \"time\" ) //主协程退出了,其它子协程也要跟着退出 func main() { go func() { i := 0 for { i++ fmt.Println(\"子协程 i = \", i) time.Sleep(time.Second) } }() //别忘了() i := 0 for { i++ fmt.Println(\"main i = \", i) time.Sleep(time.Second) if i == 2 { break } } }
等待其他协程执行完
runtime.Gosched()用于让出CPU时间片,让出当前goroutine(协程)的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。
类似:接力赛,A跑了一会碰到代码runtime.Gosched()就把接力棒交给B,A歇着,B继续跑
案例:
package main import ( \"fmt\" \"runtime\" ) func main() { go func() { for i := 0; i < 5; i++ { fmt.Println(\"go\") } }() for i := 0; i < 2; i++ { //让出时间片,先让别的协议执行,它执行完,再回来执行此协程 runtime.Gosched() fmt.Println(\"hello\") } } go go go go go hello hello
runtime.Goexit() //立即结束当前协程
案例:
package main import ( \"fmt\" \"runtime\" ) func test() { defer fmt.Println(\"ccccccccccccc\") //return //终止此函数 runtime.Goexit() //终止所在的协程 fmt.Println(\"dddddddddddddddddddddd\") } func main() { //创建新建的协程 go func() { fmt.Println(\"aaaaaaaaaaaaaaaaaa\") //调用了别的函数 test() fmt.Println(\"bbbbbbbbbbbbbbbbbbb\") }() //别忘了() //特地写一个死循环,目的不让主协程结束 for { } } aaaaaaaaaaaaaaaaaa ccccccccccccc
runtime.GOMAXPROCS() //设置并行CPU核数最大值,并返回之前的值
package main import ( \"fmt\" \"runtime\" ) func main() { //n := runtime.GOMAXPROCS(1) //指定以1核运算 n := runtime.GOMAXPROCS(2) //指定以8核运算 fmt.Println(\"n = \", n) for { go fmt.Print(1) fmt.Print(0) } }
先介绍一个最简单的监控方式。
通过 runtime.NumGoroutine() 获取当前运行中的 goroutine 数量,通过它确认是否发生泄漏。
func main() { go test() go test() go test() go test() a:=runtime.NumGoroutine() fmt.Println(a) // 5 for { } }
package main import ( \"fmt\" \"time\" ) //定义一个打印机,参数为字符串,按每个字符打印 //打印机属于公共资源 func Printer(str string) { for _, data := range str { fmt.Printf(\"%c\", data) time.Sleep(time.Second) } fmt.Printf(\"\\n\") } func person1() { Printer(\"hello\") } func person2() { Printer(\"world\") } func main() { //新建2个协程,代表2个人,2个人同时使用打印机 go person1() go person2() //特地不让主协程结束,死循环 for { } }
package main import ( \"fmt\" \"time\" ) //全局变量,创建一个channel var ch = make(chan int) //定义一个打印机,参数为字符串,按每个字符打印 //打印机属于公共资源 func Printer(str string) { for _, data := range str { fmt.Printf(\"%c\", data) time.Sleep(time.Second) } fmt.Printf(\"\\n\") } //person1执行完后,才能到person2执行 func person1() { Printer(\"hello\") ch <- 666 //给管道写数据,发送 } func person2() { <-ch //从管道取数据,接收,如果通道没有数据他就会阻塞 Printer(\"world\") } func main() { //新建2个协程,代表2个人,2个人同时使用打印机 go person1() go person2() //特地不让主协程结束,死循环 for { } }
var wg sync.WaitGroup wg.Add(2) //任务数 wg.Done() //结束 wg.Wait() //等待 package main import ( \"fmt\" \"sync\" ) var wg sync.WaitGroup func main() { wg.Add(2) out := producer() consumer(out) defer fmt.Println(\"主线程结束\") wg.Wait() //等待 } //此通道只能写,不能读 func producer() chan interface{} { ch := make(chan interface{}) go func() { for i := 0; i < 5; i++ { ch <- fmt.Sprintf(\"协程1-%d\", i) //写入字符串 } defer close(ch) wg.Done() //结束 }() return ch } //此channel只能读,不能写 func consumer(data chan interface{}) { defer fmt.Println(\"读取结束\") go func() { for num := range data { fmt.Println(num) } wg.Done() //结束 }() }
以上就是GO语言协程创建使用并通过channel解决资源竞争的详细内容,更多关于GO语言协程channel解决资源竞争的资料请关注脚本之家其它相关文章!