加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang--使用channel来同步goroutine

发布时间:2020-12-16 18:34:24 所属栏目:大数据 来源:网络整理
导读:在golang中同步goroutine有2种方法,要么使用channel,要么使用sync.WaitGroup,本文就是介绍如何通过channel来同步goroutine。先看代码。 1 package main 2 3 import ( 4 " os " 5 " os/signal " 6 " runtime " 7 " log " 8 " syscall " 9 ) 10 11 const NU

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

 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,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编译代码:

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中的数字,等待退出信号。

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

$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

转贴请注明来自:格通

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读