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

 轉貼請註明來自:格通

相關文章
相關標籤/搜索