以下是要翻译的内容: 为什么下面的程序会发生死锁?

huangapple go评论68阅读模式
英文:

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 &quot;fmt&quot;
func main() {
    c := make(chan int)
    c &lt;- 5
    a := &lt;- 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 &lt;- 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 &lt;- 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 &quot;fmt&quot;
func main() {
   c := make(chan int, 1)
   c &lt;- 5
   a := &lt;- c
   fmt.Println(a)
 }

huangapple
  • 本文由 发表于 2021年9月12日 00:20:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/69144762.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定