douh9817 2019-03-22 10:19
浏览 6
已采纳

Goroutine中关键字“ go”和不包含“ go”的比较

The following code logged an error:

fatal error: all goroutines are asleep - deadlock!

package main

import "fmt"

func main() {
    ch := make(chan int)
    ch <- 1
    fmt.Println(<-ch)
}

But when I changed the code into this:

package main

import "fmt"

func assign (ch chan int) {
    ch <- 1
}

func main() {
    ch := make(chan int)
    go assign (ch)

    fmt.Println(<-ch)
}

"1" was printed out.

Then I used buffered channels:

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

"1" and "2" can also be printed out.

I'm a little confused about the situation. Thanks in advance!

  • 写回答

2条回答 默认 最新

  • dtc99987 2019-03-23 04:07
    关注

    When you are using unbuffered channel, goroutine is blocked during write until someone does the read. In your first snippet, there is an unbuffered channel and single goroutine (main goroutine). So when you are trying to write:

    ch <- 1
    

    Nobody reads from the channel yet. The main goroutine is blocked and this line is never executed:

    fmt.Println(<-ch)
    

    That's why you've got the deadlock error.

    In the second example, you still using unbuffered channel, which means write operation blocks the goroutine. But by using go you are running the second goroutine. It means even if this new goroutine will be blocked during write (in your assign function), the main goroutine will continue to work and fmt.Println(<-ch) will be executed and do the read (which in turn unblock background goroutine and assign function will finally reach the end).

    To get more understanding about channels and goroutines, this snippet will give the same result (as your second snippet):

    package main
    
    import "fmt"
    
    func print(ch chan int) {
        fmt.Println(<-ch)
    }
    
    func main() {
        ch := make(chan int)
        go print(ch)
        ch <- 1
    }
    

    When you are working with a buffered channel (third snippet), you can do N write operations without blocking goroutine (where N is the size of the buffer). That's why in your example you did 2 writes without blocking and is able to read them later. But if your buffer is less than the count of write operations, and nobody do the read, you will fall into the same blocking issues (see the explanation of 1&2 snippets).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址
  • ¥15 elmos524.33 eeprom的读写问题