以下代码记录了一个错误:
fatal error: all goroutines are asleep - deadlock!
package main
import "fmt"
func main() {
ch := make(chan int)
ch <- 1
fmt.Println(<-ch)
}
但是当我把代码改成这样的时候:
package main
import "fmt"
func assign (ch chan int) {
ch <- 1
}
func main() {
ch := make(chan int)
go assign (ch)
fmt.Println(<-ch)
}
打印出“1”。
然后我使用缓冲 channel :
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println(<-ch)
fmt.Println(<-ch)
}
“1”和“2”也可以打印出来。
我对这种情况有点困惑。提前致谢!
最佳答案
为什么会发生死锁:
在第一个代码片段中,您只有一个主 goroutine,当您尝试写入此处的 channel 时它被阻止了:
ch <- 1
因为没有人从 channel 中读取并且主 goroutine 正在等待它继续。
If the channel is unbuffered, the sender blocks until the receiver has received the value.
发件人是main
功能,接收者也是main
功能。
如何避免死锁:
为了解决这个问题,你有两个选择:
选项 1:制作 ch
像这样缓冲的 channel :
ch := make(chan int, 1) // buffer length is set to 1
来自 A Tour of Go
Sends to a buffered channel block only when the buffer is full.
因此,您可以写入 channel ,直到缓冲区已满。然后必须有人开始阅读 channel 。
选项 2: 从 goroutine 写入 channel ,就像您在第二个代码片段中所做的那样:
func assign(ch chan int) {
ch <- 1
}
func main() {
ch := make(chan int)
go assign(ch) // does not block the main goroutine
fmt.Println(<-ch) // waiting to read from the channel
}
在这种情况下 main
函数将执行到 fmt.Println(<-ch)
并在可以从 channel 读取后立即继续。
关于go - Goroutine 中关于关键字 "go"和没有关键字的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55297458/