Go语言你会停止goroutine吗

一个没有停止的goroutine

当 goroutine 内的任务,运行的太久,又或是卡死了…就会一直阻塞在系统中,变成 goroutine 泄露,或是间接造成资源暴涨,会带来许多的问题。

func main() { 
 ch := make(chan string, 6)
 go func() {
  for {
   ch <- "脑子进煎鱼了"
  }
 }()
}

1. 关闭 channel

close 机制来完成对 goroutine 的精确控制

func main() {
 ch := make(chan string, 6)
 go func() {
  for {
   v, ok := <-ch
   if !ok { //循环到ch close后, ok为false
    fmt.Println("结束")
    return
   }
   fmt.Println(v)
  }
 }()

 ch <- "煎鱼还没进锅里..."
 ch <- "煎鱼进脑子里了!"
 close(ch)
 time.Sleep(time.Second)
}

2. for range 的特性

 go func() {
  for {
   for v := range ch { //ch close时 会退出for
    fmt.Println(v)
   }
  }
 }()

3. 定期轮询 channel

func main() {
 ch := make(chan string, 6)
 done := make(chan struct{})
 go func() {
  for {
   select {
   case ch <- "脑子进煎鱼了":
   case <-done:
    close(ch)
    return
   }
   time.Sleep(100 * time.Millisecond)
  }
 }()

 go func() {
  time.Sleep(3 * time.Second)
  done <- struct{}{}
 }()

 for i := range ch {
  fmt.Println("接收到的值: ", i)
 }

 fmt.Println("结束")
}

在上述代码中,我们声明了变量 done,其类型为 channel,用于作为信号量处理 goroutine 的关闭。

而 goroutine 的关闭是不知道什么时候发生的,因此在 Go 语言中会利用 for-loop 结合 select 关键字进行监听,再进行完毕相关的业务处理后,再调用 close 方法正式关闭 channel。

若程序逻辑比较简单结构化,也可以不调用 close 方法,因为 goroutine 会自然结束,也就不需要手动关闭了。

4. 使用 context

在 context 中,我们可以借助 ctx.Done 获取一个只读的 channel,类型为结构体。可用于识别当前 channel 是否已经被关闭,其原因可能是到期,也可能是被取消了。

因此 context 对于跨 goroutine 控制有自己的灵活之处,可以调用 context.WithTimeout 来根据时间控制,也可以自己主动地调用 cancel 方法来手动关闭。

func main() {
 ch := make(chan struct{})
 ctx, cancel := context.WithCancel(context.Background())

 go func(ctx context.Context) {
  for {
   select {
   case <-ctx.Done():
    ch <- struct{}{}
    return
   default:
    fmt.Println("煎鱼还没到锅里...")
   }

   time.Sleep(500 * time.Millisecond)
  }
 }(ctx)

 go func() {
  time.Sleep(3 * time.Second)
  cancel()
 }()

 <-ch
 fmt.Println("结束")
}

“我想在 goroutineA 里去停止 goroutineB,有办法吗?”

答案是不能,因为在 Go 语言中,goroutine 只能自己主动退出,一般通过 channel 来控制,不能被外界的其他 goroutine 关闭或干掉,也没有 goroutine 句柄的显式概念。


参考文章: 脑子进煎鱼了 :https://mp.weixin.qq.com/s/tN8Q1GRmphZyAuaHrkYFEg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值