协程之间的死锁

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

Deadlock between goroutines

问题

我是你的中文翻译助手,以下是翻译好的内容:

我对Go语言还不熟悉。当我注释掉第二个goroutine时,会出现致命错误。我不明白是什么原因导致了这个错误的发生。你能解释一下吗?

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan int)
	go func() { 
		for i := 0; i < 10; i++ {
			ch <- i
		}
	} ()
	// go func() { 
		for {
			if num, ok := <-ch; !ok {
				break
			} else {
				fmt.Printf("%d\n", num)
			}
		}
	// } ()
	time.Sleep(2 * time.Second)
	close(ch)
}

这段代码输出以下内容:

0
1
2
3
4
5
6
7
8
9
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
	/tmp/sandbox169127128/main.go:17 +0xa0

程序已退出。

希望对你有帮助!

英文:

I'm new to Go. When I comment out the second goroutine, there is a fatal error. I don't understand what causes this error to occur. Can you explain it to me?

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func main() {
	ch := make(chan int)
	go func() { 
		for i := 0; i &lt; 10; i++ {
			ch &lt;- i
		}
	} ()
	// go func() { 
		for {
			if num, ok := &lt;-ch; !ok {
				break
			} else {
				fmt.Printf(&quot;%d\n&quot;, num)
			}
		}
	// } ()
	time.Sleep(2 * time.Second)
	close(ch)
}

This prints the following code:

0
1
2
3
4
5
6
7
8
9
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
	/tmp/sandbox169127128/main.go:17 +0xa0

Program exited.

答案1

得分: 5

接收循环在从发送goroutine接收到所有值后,阻塞在从ch接收上。运行时检测到程序被阻塞并引发恐慌。

修复方法是在发送完所有值后关闭通道:

go func() { 
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
} ()

在关闭的通道上接收会产生值0, false。接收循环在接收到false值时中断。

从程序末尾删除close(ch)

在 playground 上运行

英文:

The receiving for loop blocks on receive from ch after receiving all values from the sending goroutine. The runtime detects that the program is stuck and panics.

The fix is to close the channel after sending all values:

go func() { 
    for i := 0; i &lt; 10; i++ {
        ch &lt;- i
    }
    close(ch)
} ()

Receive on the closed channel yields the value 0, false. The receiving for loop breaks on the false value.

Remove close(ch) from the end of the program.

Run it on the playground.

答案2

得分: 2

因为在第一个goroutine退出之前没有关闭通道。下面的代码应该可以工作。

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() { 
        for i := 0; i < 10; i++ {
            ch <- i
        }
        close(ch)
    } ()
    //go func() { 
        for {
            if num, ok := <-ch; !ok {
                break
            } else {
                fmt.Printf("%d\n", num)
            }
        }
    //} ()
    time.Sleep(2 * time.Second)
}

在这里尝试一下:https://play.golang.org/p/OdxNqbaZmj

英文:

Because you're not closing the channel before the first goroutine exits. The below code should work.

package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
)

func main() {
    ch := make(chan int)
    go func() { 
        for i := 0; i &lt; 10; i++ {
            ch &lt;- i
        }
        close(ch)
    } ()
    //go func() { 
        for {
            if num, ok := &lt;-ch; !ok {
                break
            } else {
                fmt.Printf(&quot;%d\n&quot;, num)
            }
        }
    //} ()
    time.Sleep(2 * time.Second)
}

Try it out here: https://play.golang.org/p/OdxNqbaZmj

huangapple
  • 本文由 发表于 2017年4月9日 00:22:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/43297474.html
匿名

发表评论

匿名网友

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

确定