英文:
Channels Deadlock
问题
我正在使用Go语言和通道构建一个异步B树,但是我遇到了错误fatal error: all goroutines are asleep - deadlock!
。我不知道为什么会出现这个错误,因为我正在使用带有缓冲通道的for循环从通道中获取值。
type Obj interface {
Compare(node Obj) int
}
type Tree struct {
Item Obj
Right, Left *Tree
height int16
}
func NewTree() *Tree {
return &Tree{Item: nil, Right: nil, Left: nil, height: 0}
}
func InOrder(t *Tree, chTree chan Obj) {
if t != nil {
InOrder(t.Left, chTree)
chTree <- t.Item
InOrder(t.Right, 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!
请帮我翻译以上内容。
英文:
I'm building an asynchronous Btree in Go with channels, but I'm getting the error fatal error: all goroutines are asleep - deadlock!
I don't know why 'cause I'm getting the values from the channel in a for loop with a buffered 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
}
}
Output:
1
2
3
4
5
6
7
8
9
10
fatal error: all goroutines are asleep - deadlock!
答案1
得分: 3
你没有关闭通道。你会注意到它实际上是正确打印的,然后出现问题。
在对通道进行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)
}
}
英文:
You're not closing the channel. You'll notice that it's actually printing correctly, then freaking out.
In a range
over a channel, like this:
for obj := range result {
//...
}
The loop will only exit if you call close(result)
. In this case it's a bit tricky because of the recursive nature. Ultimately I'd recommend wrapping the call to InOrder
like so:
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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论