当前位置: 首页 > 面试题库 >

如何捕获通道死锁的异常?

尉迟默
2023-03-14
问题内容

我正在学习Go,并且正在通过GoTours 学习此课程。到目前为止,这就是我所拥有的。

package main

import (
    "fmt"
    "code.google.com/p/go-tour/tree"
)

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
    if t != nil {
        Walk(t.Left, ch)
        ch <- t.Value
        Walk(t.Right, ch)
    }
}

func main() {
    var ch chan int = make(chan int)
    go Walk(tree.New(1), ch)
    for c := range ch {
        fmt.Printf("%d ", c)    
    }
}

如您所见,我尝试通过打印输出到通道中的值来测试Walk函数。但是,出现以下错误。

1 2 3 4 5 6 7 8 9 10 throw: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    main.go:25 +0x85

goroutine 2 [syscall]:
created by runtime.main
    /usr/local/go/src/pkg/runtime/proc.c:221

exit status 2

我认为应该会出现此错误,因为我从不使用close该通道。但是,有没有一种方法可以“捕获”此死锁错误并以编程方式对其进行处理?


问题答案:

死锁类似于nil指针引用,它表示程序中的一个BUG。因此,此类错误通常无法恢复。

如lbonn所述,这里的问题是您需要“关闭(myChan)”您的频道。如果不执行此操作,则该范围将永远等待下一个元素。

您可以尝试如下操作:

func main() {
    var ch chan int = make(chan int)
    go func() {
        Walk(tree.New(1), ch)
        close(ch)
    }()
    for c := range ch {
        fmt.Printf("%d ", c)
    }
}

如果要并行遍历树,则需要进行进一步的更改:

package main

import (
    "code.google.com/p/go-tour/tree"
    "fmt"
    "sync"
)

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int, done *sync.WaitGroup) {
    if t != nil {
        done.Add(2)
        go Walk(t.Left, ch, done) //look at each branch in parallel
        go Walk(t.Right, ch, done)
        ch <- t.Value
    }
    done.Done()
}

func main() {
    var ch chan int = make(chan int, 64) //note the buffer size
    go func() {
        done := new(sync.WaitGroup)
        done.Add(1)
        Walk(tree.New(1), ch, done)
        done.Wait()
        close(ch)
    }()
    for c := range ch {
        fmt.Printf("%d ", c)
    }
}


 类似资料:
  • 问题内容: 我最近开始学习Go语言,但是遇到了问题。我有一个简单的go例程,该例程可以将值返回或将值推入通道。我的主要fn代表一直在执行此例程,直到满足条件或数据用尽为止。这段代码似乎在“找到”频道上陷入僵局。我究竟做错了什么? 有多名工人 可以同时在多个工人中找到物品 一旦找到物品,所有工人应停止。 。 问题答案: 一种可能的解决方案是避免使用select语句,并为接收者(或发送者,或两者)使用

  • 我遇到了围棋频道的奇怪行为。问题描述如下。 当我运行上面的代码时,我得到如下结果: 频道ch的len和cap看起来很复杂,但代码仍然有效。当我运行此代码时: 结果是:len:0 cap:0是nil:false致命错误:所有goroutine都处于Hibernate状态-死锁! 更重要的是,当我更改第二个代码块时,如下所示:package main 事情又起了作用,我得到了: 那么,谁能告诉我以下问

  • 问题内容: 由于以下代码中的某种原因,我收到“致命错误:所有goroutine都在睡眠-死锁!”。我正在使用应该不阻塞的缓冲通道。不知道我在做什么错 游乐场链接https://play.golang.org/p/J9meD5aKna 问题答案: 虽然您的解决方案可能会起作用,但我对此并不满意。 首先,您需要更改通道大小以使其起作用这一事实表明存在潜在的问题/错误。现在,每次您要启动另一个时,都必须

  • 本文向大家介绍如何捕获 setTimeout 异常相关面试题,主要包含被问及如何捕获 setTimeout 异常时的应答技巧和注意事项,需要的朋友参考一下 No description provided.

  • 我试图编写“好的”python并捕获一个S3,但没有这样的关键错误: 但是NoSuchKey没有定义,我无法跟踪到需要定义的导入。 是但是botocore.errorfactory导入的给出了一个错误,botocore.errorfactory导入的

  • 问题内容: 我们在工作中使用JUnit 3,并且没有注释。我想在我们的代码中添加一个实用程序来包装它: 所以我尝试了这个: 但是,我认为Java无法在catch块中使用通用异常类型。 围绕Java限制,我该怎么做? 有没有办法检查变量的类型? 问题答案: 您可以传入Class对象并以编程方式进行检查。 我不确定您是否要重新扔球;重新抛出将同样导致测试失败/错误,但是从语义上讲我不会,因为它基本上意