golang--使用channel来同步goroutine

系统管理员 2022-01-15 01:11 376阅读 0赞

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在golang中同步goroutine有2种方法,要么使用channel,要么使用sync.WaitGroup,本文就是介绍如何通过channel来同步goroutine。先看代码。

  1. 1 package main 2
  2. 3 import ( 4 "os"
  3. 5 "os/signal"
  4. 6 "runtime"
  5. 7 "log"
  6. 8 "syscall"
  7. 9 ) 10
  8. 11 const NUM_OF_QUIT int = 100
  9. 12
  10. 13 func main() { 14 runtime.GOMAXPROCS(runtime.NumCPU()) 15 done := make(chan bool) 16 receive_channel := make(chan chan bool) 17 finish := make(chan bool) 18
  11. 19
  12. 20 for i := 0; i < NUM_OF_QUIT; i++ { 21 go do_while_select(i, receive_channel, finish) 22 } 23
  13. 24 go handle_exit(done, receive_channel, finish) 25
  14. 26 <-done 27 os.Exit(0) 28
  15. 29 } 30 func handle_exit(done chan bool, receive_channel chan chan bool, finish chan bool) { 31 sigs := make(chan os.Signal, 1) 32 signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 33 chan_slice := make([]chan bool, 0) 34 for { 35 select { 36 case <-sigs: 37 for _, v := range chan_slice { 38 v <- true
  16. 39 } 40 for i := 0; i < len(chan_slice); i++ { 41 <-finish 42 } 43 done <- true
  17. 44 runtime.Goexit() 45 case single_chan := <-receive_channel: 46 log.Println("the single_chan is ", single_chan) 47 chan_slice = append(chan_slice, single_chan) 48 } 49 } 50 } 51 func do_while_select(num int, rece chan chan bool, done chan bool) { 52 quit := make(chan bool) 53 rece <- quit 54 for { 55 select { 56 case <-quit: 57 done <- true
  18. 58 runtime.Goexit() 59 default: 60 //简单输出
  19. 61 log.Println("the ", num, "is running") 62 } 63 } 64 }

上面的代码保存为example.go,通过gotool编译代码:

  1. go build example.go

在当前目录下有example文件,在终端运行这个文件

  1. 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running 2013/03/19 21:17:14 the 0 is running
  2. ......

上面不断输出goroutine中的数字,等待退出信号。

新打开一个终端,通过ps找到这个进程名,通过kill工具干掉这个进程:

  1. $ps aux | grep example user 4026 77.9 0.0 39436 1716 pts/1 Sl+ 21:19 0:17 ./example $kill 4026

不久就可以看到在第一个终端里面不再打印,至此演示完毕。

代码思想:

新建NUM_OF_QUIT个goroutine,这些个goroutine里面新建1个chan bool,通过这个channel来接受退出的信号,这些channel在新建的时候,已经发给了handle_exit。在handle_exit这个goroutine里面,1方面监控由系统发过来的退出信号,然后再通知其他的goroutin优雅地退出;另一方面通过slice收集其他goroutine发过来的channel。handle_exit通知其他的goroutine优雅退出后,再发信号给main进程主动退出。

可以修改NUM_OF_QUIT值,例如改为10000,这个时候,kill命令发出去后,要等待相当长的一段时间才能看到第一个终端停止打印。

参考:

Go by Example: Signals

https://gobyexample.com/signals

转贴请注明来自:格通

转载于:https://my.oschina.net/u/191928/blog/618675

发表评论

表情:
评论列表 (有 0 条评论,376人围观)

还没有评论,来说两句吧...

相关阅读

    相关 动态创建goroutinechannel

    若各位看官有其它较好的思想和方式,欢迎留言共同交流。 动态的创建需求一般应用于动态的数据量、动态的时间等,比如这里遇到的可能是数十万、百万左右的数据量推送。可以采取的方式比如

    相关 golang channel使用

    本文对channel使用中的几个疑惑,以例子的形式加以说明。 普通channel 缺省情况下,发送和接收会一直阻塞着,直到另一方准备好. 例如: pack