go - channel 僵局

标签 go deadlock goroutine

我正在使用 channel 在 Go 中构建一个异步 Btree,但我收到错误 fatal error: all goroutines are asleep - deadlock! 我不知道为什么因为我在带有缓冲 channel 的 for 循环中从 channel 中获取值。

type Obj interface {
    Compare(node Obj) int
}

type Tree struct {
    Item        Obj
    Rigth, Left *Tree
    height      int16
}

func NewTree() *Tree {
    return &Tree{Item: nil, Rigth: nil, Left: nil, height: 0}
}

func InOrder(t *Tree, chTree chan Obj) {
    if t != nil {
        InOrder(t.Left, chTree)
        chTree <- t.Item
        InOrder(t.Rigth, chTree)
    }
}

// == testing ==

func TestInOrder(t *testing.T) {
    tree := NewTree()
    nums := []int{9, 7, 2, 4, 6, 10, 1, 5, 8, 3}
    for i := 0; i < len(nums); i++ {
        tree.Insert(ObjInt{nums[i]})
    }
    result := make(chan Obj, 10)
    go InOrder(tree, result)
    var previous Obj
    for obj := range result {
        fmt.Println(obj)
        if previous == nil {
            previous = obj
            continue
        }
        assertTrue(previous.Compare(obj) == -1, t,
            "Previous obj should be smaller than current object")
        previous = obj
    }
}

输出:

1
2
3
4
5
6
7
8
9
10

fatal error: all goroutines are asleep - deadlock!

最佳答案

您没有关闭 channel 。您会注意到它实际上打印正确,然后吓坏了。

在 channel 上的 range 中,如下所示:

for obj := range result {
     //...
}

只有调用 close(result) 时循环才会退出。在这种情况下,由于递归的性质,它有点棘手。最后,我建议像这样包装对 InOrder 的调用:

func InOrder(t *Tree, chTree chan obj) {
    inOrder(t, chTree)
    close(chTree)
}

func inOrder(t *Tree, chTree chan Obj) {
    if t != nil {
        inOrder(t.Left, chTree)
        chTree <- t.Item
        inOrder(t.Rigth, chTree)
    }
}

关于go - channel 僵局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23316798/

相关文章:

go - 有什么方法可以检查值是否缓冲在 Go chan 中?

调用 select() 时,Java 线程在向选择器注册 channel 时阻塞。该怎么办?

java - 即使正在释放许可证,Semaphore 类也会陷入僵局吗?

go - 如何将 JSON 字符串转换为字节数组?

javascript - 无法使用 Highchart API 构建多级钻取图表

mysql - InnoDB 死锁未提交读! - Java - Glassfish - EJB3 (JPA/Hibernate)

arrays - Golang 字节数组通过 channel 通信丢失数据

go - 在 Goroutine 中等待管道 io.Copy 时发生死锁

Go编程语言接口(interface)概念理解

go - 如何在Golang中通过引用传递具有值类型接口(interface)的 map slice