1. 首页
  2. 主题
  3. Go问与答

为啥以下代码会产生deadlock?

linture · · 1148 次点击
``` import ( "fmt" ) func main() { AlterPrint() } // POINT: communicate between goroutines by channel func AlterPrint(){ letter, number := make(chan bool), make(chan bool) letterDone := make(chan bool) numberDone := make(chan bool) go func() { i := 1 for { if i > 28 { numberDone <- true return } select{ case <-number: { fmt.Print(i) i++ fmt.Print(i) i++ letter <- true break } default: { break } } } }() go func(){ i := 'A' for { if i > 'Z' { letterDone <- true return } select{ case <-letter: { fmt.Print(string(i)) i++ fmt.Print(string(i)) i++ number <- true break } default: { break } } } }() number <- true <- letterDone <- numberDone } ``` I expect the output of "12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728", but the actual output is ``` goroutine 1 [chan receive]: main.AlterPrint() /tmp/54841538.go:66 +0x183 main.main() /tmp/54841538.go:7 +0x14 goroutine 5 [chan send]: main.AlterPrint.func1(0xc82000c240, 0xc82000c180, 0xc82000c120) /tmp/54841538.go:31 +0x25a created by main.AlterPrint /tmp/54841538.go:40 +0xde exit status 2 ```
stayfoo
stay hungry stay foolish
1、两个goroutine中的代码,在互相等待 chan 的值 `number` 和 `letter` 永远不会接收到数据,导致 numberDone 和 letterDone 也永远不会接收到数据。 ```go case &lt;-number: { fmt.Print(i) i++ fmt.Print(i) i++ letter &lt;- true break } ``` ```go case &lt;-letter: { fmt.Print(string(i)) i++ fmt.Print(string(i)) i++ number &lt;- true break } ``` 2、发送到 chan 的数据,没有被接收。 main 中最后 `number &lt;- true` ,发送给 number 了一个true,没有被接收。 使用如下代码就不会崩溃: ``` number &lt;- true fmt.Println(&#34;number: &#34;, &lt;- number) ```
#2
更多评论
```go package main import ( &#34;fmt&#34; ) func main() { AlterPrint() } // POINT: communicate between goroutines by channel func AlterPrint(){ letter, number := make(chan bool), make(chan bool) letterDone := make(chan bool) numberDone := make(chan bool) go func() { i := 1 for { if i &gt; 28 { numberDone &lt;- true return } select{ case &lt;-number: { fmt.Print(i) i++ fmt.Print(i) i++ if i != 29 { letter &lt;- true } break } default: { break } } } }() go func(){ i := &#39;A&#39; for { if i &gt; &#39;Z&#39; { letterDone &lt;- true return } select{ case &lt;-letter: { fmt.Print(string(i)) i++ fmt.Print(string(i)) i++ number &lt;- true break } default: { break } } } }() number &lt;- true &lt;- letterDone &lt;- numberDone } ```
#1
Solved. letterDone 被读出之后,第二个goroutine完全退出,第一个goroutine阻塞在了letter &lt;- true,主线程阻塞在了&lt;- numberDone。@StoneFlying&#39;s answer solved this dead lock.
#3

用户登录

没有账号?注册

今日阅读排行

    加载中

一周阅读排行

    加载中