英文:
Why is the following program deadlock?
问题
以下是您提供的代码的中文翻译:
package main
import "fmt"
func main() {
c := make(chan int)
c <- 5
a := <- c
fmt.Println(a)
}
在这段代码中,数据被发送到通道并从通道接收,但仍然显示错误:
fatal error: all goroutines are asleep - deadlock!
请注意,这段代码中存在死锁错误。死锁通常发生在并发程序中,当所有的goroutine都无法继续执行时发生。在这种情况下,主goroutine在发送数据到通道后被阻塞,而没有其他goroutine来接收数据,导致死锁错误。要解决这个问题,您可以使用goroutine来接收数据或使用带有缓冲区的通道。
英文:
package main
import "fmt"
func main() {
c := make(chan int)
c <- 5
a := <- c
fmt.Println(a)
}
Here both the data is being sent and recieved to/from the channel but still the error is being displayed:
fatal error: all goroutines are asleep - deadlock!
答案1
得分: 2
你的通道 c
没有任何缓冲区(甚至没有一个单元格),这意味着主 goroutine 在 c <- 5
这一行上被锁住了。由于它是你应用程序中唯一的 goroutine,这导致了死锁。
英文:
Your channel c
doesn't have any buffer (even a single cell), which means that the main goroutine locks at the c <- 5
line. Since it is the only goroutine in your application, it creates a deadlock.
答案2
得分: 2
该通道是无缓冲的。因此,如果有一个goroutine向其写入数据,并且没有其他goroutine从中读取数据,那么就会发生死锁。
要修复这个问题,可以将其改为无缓冲的通道:
c := make(chan int, 1)
或者从另一个goroutine中异步写入数据:
go func() {
c <- 5
}()
https://play.golang.org/p/RRJILbuZKTQ
由于通道用于在goroutine之间进行通信,很少有情况下会在同一个goroutine中既写入通道又读取通道。一个例外是,如果将通道用作资源池,并且希望预先填充(缓冲)通道。
英文:
The channel is unbuffered. So if one writes to it - and no other goroutine is reading from it - it is a guaranteed deadlock.
To fix, either make it unbuffered:
c := make(chan int, 1)
or write asynchronously from another goroutine:
go func() {
c <- 5
}()
https://play.golang.org/p/RRJILbuZKTQ
Since channels are used to communicate between goroutines, its extremely rare one writes to a channel from the same goroutine as the reads. An exception may be, if using a channel as a resource pool and one wants to pre-populate the (buffered) channel.
答案3
得分: 1
通道 make(chan int) 具有隐式大小为零(参考:https://golang.org/ref/spec#Making_slices_maps_and_channels)
大小为零的通道是无缓冲的。指定大小的通道 make(chan int, n) 是有缓冲的。有关有缓冲和无缓冲通道的讨论,请参阅 http://golang.org/ref/spec#Send_statements。示例 http://play.golang.org/p/VZAiN1V8-P 说明了它们之间的区别。
在这里,channel <- c 或 c <- 的操作将被阻塞,直到有其他协程处理它。因此,将 c := make(chan int) 更改为 c := make(chan int, 1)
package main
import "fmt"
func main() {
c := make(chan int, 1)
c <- 5
a := <- c
fmt.Println(a)
}
英文:
Channels make(chan int) has implicit size zero ( ref: https://golang.org/ref/spec#Making_slices_maps_and_channels)
A channel of size zero is unbuffered. A channel of specified size make(chan int, n) is buffered. See http://golang.org/ref/spec#Send_statements for a discussion on buffered vs. unbuffered channels. The example at http://play.golang.org/p/VZAiN1V8-P illustrates the difference.
Here, channel <-c or c <- will be blocked until someone processes it (concurrently). So, change c := make(chan int) to c := make(chan int,1)
package main
import "fmt"
func main() {
c := make(chan int, 1)
c <- 5
a := <- c
fmt.Println(a)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论