返回顶部
首页 > 资讯 > 精选 >停止无限期写入通道的 goroutine
  • 828
分享到

停止无限期写入通道的 goroutine

2024-02-06 05:02:36 828人浏览 八月长安
摘要

问题内容 我有一个函数可以创建一个无限期填充通道的 Goroutine,例如: func foo()

问题内容

我有一个函数可以创建一个无限期填充通道的 Goroutine,例如:

func foo() <-chan int {
  ch := make(chan int) 
  go func() {
    defer close(ch)
    for {
      ch <- 1
    } 
  }() 
  return ch
}

假设我们有一个消费者想在一段时间后停止:

ch:=foo() 
<-ch
<-ch
// done

现在我想清理 goroutine 资源,包括通道。我尝试为此添加一个“完成”通道,但随后我遇到了僵局:

func Foo() (<-chan int, chan<- bool) {
  ch := make(chan int)
  done := make(chan bool)
  go func() {
    defer close(ch)
    for {
      select {
      case <-done:
          return
      default:
          ch <- 1
      }
    } 
  }() 
  return ch, done
}

func main() {
  ch, done := Foo()
  <-ch
  <-ch
  done <- true
  // HERE
}

现在,它似乎可以工作,但这只是因为程序退出,如果我用一些io操作替换// here(例如:Http.get(“http://google.com”)) ,我面临死fatal 错误:所有 goroutine 都在睡觉 - 死锁!)。 我想知道是否有另一种方法可以清理由 foo 函数创建的生成的 goroutine 和通道。


正确答案


只需在启动的 goroutine 中将 default 替换为 case 即可:

func Foo() (<-chan int, chan<- bool) {
  ch := make(chan int)
  done := make(chan bool)
  go func() {
    defer close(ch)
    for {
      select {
      case <-done:
          return
      case ch <- 1:
      }
    } 
  }() 
  return ch, done
}

原代码在default情况下出现死锁的原因如下:

  • 当没有其他并发运行的 goroutine 写入 done 通道时,启动的写入 ch 通道的 goroutines 会立即转到 default 情况。然后 goroutine 会阻塞在 ch 行,直到其他 goroutine 从 ch 读取值。
  • 主协程从 ch 读取两次。这会导致在启动的 goroutine 处有两个成功的执行循环。然后它尝试写入 done。此时启动的goroutine可能已经检查了select语句,陷入default情况并阻塞在ch 行。因此主 goroutine 也会无限期地阻塞在 done 行。这会导致僵局。

以上就是停止无限期写入通道的 goroutine的详细内容,更多请关注编程网其它相关文章!

--结束END--

本文标题: 停止无限期写入通道的 goroutine

本文链接: https://lsjlt.com/news/561204.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作