【问题标题】:Is it one channel ops affect another channel ops一个频道操作会影响另一个频道操作吗
【发布时间】:2017-08-26 10:32:45
【问题描述】:

我做了这个简单的代码,想知道通道是如何工作的,不知何故,如果通道 b 发送后通道 c 被发送,最后一个例程中的通道不会被发送,

我有 2 个通道,通道 c 用于将通道 b 拆分为切片的 4 部分。

 package main

 import (
      "fmt"
      "strconv"
 )

 func runner(idx int, c chan []int, b chan []int) {
      var temp []int
      fmt.Println("runner " + strconv.Itoa(idx))
      bucket := <-b
      for k, v := range bucket {
           if v != 0 {
                temp = append(temp, v)
                bucket[k] = 0
           }
           if len(temp) == 5 {
                break
           }
      }

      //Strange condition if channel c is sent after channel b is sent,
      //somehow the last chan is not being sent
      b <- bucket
      c <- temp

      //this is right if channel b is sent after channel c is sent
    //c <- temp
    //b <- bucket

 }

 func printer(c chan []int) {
      for {
           select {
           case msg := <-c:
                fmt.Println(msg)
                //time.Sleep(time.Second * 1)
           }
      }
 }

 func main() {

      c := make(chan []int, 5)
      bucket := make(chan []int)

      go runner(1, c, bucket)
      go runner(2, c, bucket)
      go runner(3, c, bucket)
      go runner(4, c, bucket)

      bucket <- []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

      go printer(c)

      var input string
      fmt.Scanln(&input)

 }

【问题讨论】:

  • 这段代码对你来说实际上不清楚的地方并不明显。您期望得到什么以及实际得到什么?
  • 你运行代码了吗?请检查 runner 功能,如果你先发送到通道 c 然后 b,你将有正确的条件,这是我不明白的,我希望有人解释这个通道行为
  • "你会有正确的条件" ---这就是问题的问题:你没有解释什么是“正确”,什么是“错误”。 PS:请尽量避免使用“c”、“u”、“b”等缩写。
  • 谢谢@zerkms,kennytm 指出来吧

标签: go channel


【解决方案1】:
  bucket := make(chan []int)

您的b 频道的容量为 0。这意味着每当您向该频道发送内容时,该频道会立即满并会阻塞,直到接收者读取该频道。

当只剩下一个runner时,没有人会调用bucket := &lt;-b来读取最后一个bucket,因此最后一个goroutine永远卡在b &lt;- bucket行,因此下一行c &lt;- temp永远不会为最后一个 goroutine 调用。

【讨论】:

  • 啊,我现在看到了,没有其他例程读取通道&lt;-b,所以它将永远停留在b &lt;- bucket,所以我在打印机功能上进行了更改以读取b通道func printer(c chan []int, b chan []int) { for { select { case msg := &lt;-c: fmt.Println(msg) //time.Sleep(time.Second * 1) case msg := &lt;-b: fmt.Println(msg) } } }
  • 非常非常非常感谢
  • 问题是没有人读取最后一个b通道,所以它会卡住或阻塞
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-17
  • 2021-11-08
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 2019-05-17
相关资源
最近更新 更多