首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我的围棋程序会陷入僵局?

为什么我的围棋程序会陷入僵局?
EN

Stack Overflow用户
提问于 2016-05-11 08:25:23
回答 2查看 50关注 0票数 0

我对戈朗编程非常陌生,我有下面的程序来生成deadlock,我不明白为什么?

另一件事是,如果我关闭doAdd方法中的通道,然后进入无限循环,这对我来说也有点奇怪。

这是节目。

代码语言:javascript
复制
var wg sync.WaitGroup

func main() {

    ch1 := make(chan string)
    ch2 := make(chan string)
    ch3 := make(chan string)
    chClose := make(chan bool)
    wg.Add(3)
    go doAdd(ch1, "ch1")
    go doAdd(ch2, "ch2")
    go doAdd(ch3, "ch3")

    go waitForClose(chClose)

    for {
        select {
        case x := <-ch1:
            fmt.Println("Got from ch1 ", x)
        case y := <-ch2:
            fmt.Println("Got from ch2 ", y)
        case z := <-ch3:
            fmt.Println("Got from ch3 ", z)
        case <-chClose:
            fmt.Println("CLOSED")
            break
        }
    }
}

func waitForClose(chClose chan bool) {
    wg.Wait()
    chClose <- true
}

func doAdd(ch chan string, name string) {
    for i := 0; i < 10; i++ {
        ch <- strconv.Itoa(i)
    }
    wg.Done()
}

产出如下:

代码语言:javascript
复制
Got from ch1  0
Got from ch1  1
Got from ch1  2
Got from ch1  3
Got from ch1  4
Got from ch1  5
Got from ch1  6
Got from ch1  7
Got from ch1  8
Got from ch1  9
Got from ch2  0
Got from ch2  1
Got from ch2  2
Got from ch2  3
Got from ch2  4
Got from ch2  5
Got from ch2  6
Got from ch2  7
Got from ch2  8
Got from ch2  9
Got from ch3  0
Got from ch3  1
Got from ch3  2
Got from ch3  3
Got from ch3  4
Got from ch3  5
Got from ch3  6
Got from ch3  7
Got from ch3  8
Got from ch3  9
CLOSED
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select]:
main.main()
        c:/PraveenData/demo/go-work/main.go:29 +0x915
exit status 2
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-11 08:37:30

出现死锁的原因是,您的break中的select只从select中分离出来,使得for循环可以自由地重新输入select,在那里没有一个通道可以读取。

你可以这样做来拯救这一切:

代码语言:javascript
复制
done := false

for !done {
        select {
               ...
        case <-chClose:
                done = true
                fmt.Println("CLOSED")
        }
}

这在很小程度上允许for循环终止。

另一种方法是使用标签:

代码语言:javascript
复制
OuterLoop:
        for {
                select {
                ...
                case <-chClose:
                        fmt.Println("CLOSED")
                        break OuterLoop
                }
        }

在这种情况下,我个人对第一个版本略有偏爱,但这只是品味问题。

票数 2
EN

Stack Overflow用户

发布于 2016-05-11 08:34:31

程序末尾的break只会脱离select (并再次进入循环,从而导致死锁):用return替换它可以很好:https://play.golang.org/p/j5bDaj3z7y

实际上,来自规格说明

一个“中断”语句在同一个函数中终止最内部的"for“、"switch”或"select“语句的执行。

您可以使用return (就像我所做的那样)、goto或其他架构重构来解决这个问题。

至于无限循环,这是相同的问题,相反,关闭的通道总是返回,所以当break退出select时,输入回循环,并永远从关闭的通道接收nil

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37156960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档