douqiu9529 2019-05-22 05:27
浏览 79
已采纳

仅向通道发送值时进入工作流程

I am learning channels in Go by following this tutorial. When I only send value to a channel it gives error. Here is the example code.

package main

import "fmt"

func main() {
  ch := make(chan int)
  ch <- 1

  fmt.Println("Does not work")
}

Here I am just sending value to the channel but not receiving anything. It give an error

fatal error: all goroutines are asleep - deadlock! 

But when I run following code it doesn't give any error

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)

    fmt.Println("did not receive but still works")
}

and prints

did not receive but still works

I couldn't understand why it works in second case while it does not work in first case. Even though I have not received any value for the channel in both cases. Also what is causing the deadlock in first case and how it gets avoided in second case?

  • 写回答

1条回答 默认 最新

  • douju1365 2019-05-22 06:38
    关注

    Neither example works. In fact, no example that only sends to a channel will ever work, in any traditional sense of "work".

    But here's a step through of each, to make it clear:

    First example

    ch := make(chan int)
    

    This creates an unbuffered channel. Unbuffered channels don't hold any data, they only act as a conduit for communication--all data sent must be received by something else, before the program execution proceeds--on either side of the channel.

    ch <- 1
    

    Here you send data on the channel, but nothing is waiting to receive it, so the program waits. In this case, it waits forever, because you never created a receiver for the channel, thus your deadlock.

    Second example

    c := make(chan int)
    

    Again, create an unbuffered channel.

    go sum(s[:len(s)/2], c)
    

    Call the sum function, which, incidentally, will also block forever, for the reasons described above--nothing is receiving on the channel, so it will wait forever. However, in this case, you've called it in a goroutine. The goroutine will run in a separate execution thread, while other bits of the program run. Although, due to never receiving data from the channel, this goroutine will never exit, until the main program exits.

    go sum(s[len(s)/2:], c)
    

    Again, you call sum, and again, in a goroutine. So at this point, you have three gorotuines: One running main(), and one each running an invocation of sum(). The latter two will never exit.

    Then your program exits. When the program exits, all goroutines (including the two that are stuck forever waiting on your channel) exit.

    Since this program exits immediately, the deadlock is never reported, but it does assuredly exist, same as in your first example.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记