golang--使用channel来同步goroutine

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

 1 package main  2 
 3 import (  4     "os"
 5     "os/signal"
 6     "runtime"
 7     "log"
 8     "syscall"
 9 ) 10 
11 const NUM_OF_QUIT int = 100
12 
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 
19 
20     for i := 0; i < NUM_OF_QUIT; i++ { 21  go do_while_select(i, receive_channel, finish) 22  } 23 
24  go handle_exit(done, receive_channel, finish) 25 
26     <-done 27     os.Exit(0) 28 
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
39  } 40             for i := 0; i < len(chan_slice); i++ { 41                 <-finish 42  } 43             done <- true
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
58  runtime.Goexit() 59         default: 60             //简单输出
61             log.Println("the ", num, "is running") 62  } 63  } 64 }

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

go build example.go

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

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
......

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

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

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

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

代码思想:blog

新建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命令发出去后,要等待至关长的一段时间才能看到第一个终端中止打印。get

参考:同步

Go by Example: Signals

https://gobyexample.com/signals

 转贴请注明来自:格通

相关文章
相关标签/搜索