创建协程
goroutine是go的设计核心,就是协程
主协程终止了,子协程也终止
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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 } } |
主协程终止,子协程也终止
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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时间片
等待其他协程执行完
runtime.Gosched()用于让出CPU时间片,让出当前goroutine(协程)的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。
类似:接力赛,A跑了一会碰到代码runtime.Gosched()就把接力棒交给B,A歇着,B继续跑
案例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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 |
Goexit立即结束当前协程
1
|
runtime.Goexit() //立即结束当前协程 |
案例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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 |
GOMAXPROCS设置并行CPU核数最大值,并返回之前的值
1
|
runtime.GOMAXPROCS() //设置并行CPU核数最大值,并返回之前的值 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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数量
先介绍一个最简单的监控方式。
通过 runtime.NumGoroutine() 获取当前运行中的 goroutine 数量,通过它确认是否发生泄漏。
1
2
3
4
5
6
7
8
9
10
|
func main() { go test() go test() go test() go test() a:=runtime.NumGoroutine() fmt.Println(a) // 5 for { } } |
多任务资源竞争问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package main import ( "fmt" "time" ) //定义一个打印机,参数为字符串,按每个字符打印 //打印机属于公共资源 func Printer(str string) { for _, data := range str { fmt.Printf( "%c" , data) time.Sleep(time.Second) } fmt.Printf( " " ) } func person1() { Printer( "hello" ) } func person2() { Printer( "world" ) } func main() { //新建2个协程,代表2个人,2个人同时使用打印机 go person1() go person2() //特地不让主协程结束,死循环 for { } } |
通过channel解决资源竞争问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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( " " ) } //person1执行完后,才能到person2执行 func person1() { Printer( "hello" ) ch <- 666 //给管道写数据,发送 } func person2() { <-ch //从管道取数据,接收,如果通道没有数据他就会阻塞 Printer( "world" ) } func main() { //新建2个协程,代表2个人,2个人同时使用打印机 go person1() go person2() //特地不让主协程结束,死循环 for { } } |
主协程如何等其余协程完再退出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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解决资源竞争的资料请关注服务器之家其它相关文章!
原文链接:https://www.cnblogs.com/guyouyin123/p/13985447.html