【问题标题】:Closing channel on multiple coroutines在多个协程上关闭通道
【发布时间】:2022-01-28 00:08:00
【问题描述】:

如果我有多个 goroutine 读写同一个通道,有什么方法可以在某个时间点关闭通道,例如在写入固定数量的元素之后。


func foo(c chan int) {
    for i := range c {
        // how to close the channel after 100 integers are written?
        c <- i + 1
        c <- i + 2
    }
}

func bar() {
    c := make(chan int, 200)
    c <- 0
    go foo(c)
    go foo(c)
    go foo(c)
}

【问题讨论】:

  • 一个频道只能关闭一次。如果您有多个发件人,则必须协调他们。见Closing channel of unknown length
  • 你通常不希望在这样的 goroutine 中从同一个通道接收和发送,因为它使通道和数据的所有权难以确定,并且很容易产生死锁。您要解决的问题是什么?
  • 这能回答你的问题吗? Closing channel of unknown length
  • @icza Waitgroup 在我知道发件人何时完成时很有用,但在这种情况下,发件人处于通道接收循环中,很难确定何时在 waitgroup 上完成
  • @JimB 我正在尝试编写一个 sha256 蛮力程序,每次从通道接收一个字符串都会发回 n 个字符串,例如接收“a”,发送“aa”,...,“az”

标签: go concurrency goroutine


【解决方案1】:

Give 有条件的情况会适用:

for i := 0; i <= cap(c); i++ {
        // how to close the channel after 100 integers are written? 
        c <- i + 1
        // since you send 2 values to channel for each i loop, you need to half of it.
        if i == 49 { //if you asking why 49, you have sent one value on bar function. Also to make it perfectly 100 integer in total.
             close(ch)
             break // terminating the function after the closing channel, it will run in panic because the function still running and keep sending value on channel which was already closed.
        }
        c <- i + 2
}
Output :
0
1
2
2
3
3
...
50
50

只提供一些关于频道的信息,如果你还没有在频道上发送任何内容,请不要使用频道范围... 如果您在通道值之前放置“i range channel”,它将不会读取任何内容。

再次回到您的代码 如果你运行这段代码:

func bar() {
    c := make(chan int, 200)
    c <- 0
    go foo(c)
    go foo(c) // run in panic
    go foo(c) // run in panic
}

它将在恐慌中运行,因为通道已经关闭,这意味着您的通道不再接受任何值。

看看这张图片,假设你制作了一个容量为 3 的缓冲通道。如果您尝试再次在其上发送值,您将在收到 2 个要发送的值后关闭它会在恐慌中运行。

【讨论】:

  • 如果我需要多个 goroutine 来处理数据怎么办?还是我应该避免这样做?
  • 只要你知道自己在做什么,就去做吧。您还需要更好地理解并发性,它们是如何工作的……您可以尝试阅读有关它的文献书籍或任何来源。但是 go tour 已经足够了解它是如何工作的了。所以让你的想象力在代码xD上成真
猜你喜欢
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
相关资源
最近更新 更多