在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
參考:同步
https://gobyexample.com/signals
轉貼請註明來自:格通