Concurrency 即使通道关闭,go例程也会死锁
我有一个列表,有一个函数从中弹出元素,还有一个函数“接收”弹出的元素。我原以为在接收器之后关闭会关闭通道,但似乎程序在到达那里之前就死锁了。这样做的最佳方式是什么?我是否应该有另一个频道来检测pop何时完成Concurrency 即使通道关闭,go例程也会死锁,concurrency,go,goroutine,Concurrency,Go,Goroutine,我有一个列表,有一个函数从中弹出元素,还有一个函数“接收”弹出的元素。我原以为在接收器之后关闭会关闭通道,但似乎程序在到达那里之前就死锁了。这样做的最佳方式是什么?我是否应该有另一个频道来检测pop何时完成 func-pop(列表*[]int,c-chan int){ 如果len(*list)!=0{ 结果:=(*列表)[0] *列表=(*list)[1:] fmt.Println(“即将发送”,结果) c代码有很多问题,让我们看看 您的pop函数在访问切片时不会锁定,因此这就是数据竞争 fo
func-pop(列表*[]int,c-chan int){
如果len(*list)!=0{
结果:=(*列表)[0]
*列表=(*list)[1:]
fmt.Println(“即将发送”,结果)
c代码有很多问题,让我们看看
您的pop
函数在访问切片时不会锁定,因此这就是数据竞争
for len(list)>0{}
是一种数据竞争,因为您在其他两个goroutine中修改列表时正在访问列表
for len(list)>0{}
将永远不会返回,因为您的列表中有3项,但您只调用了两次pop
receiver(c)
由于#3的错误,它尝试从通道读取数据,但没有写入数据
一种方法是使用一个编写器(pop
)和多个读卡器(receiver
):
func-pop(列表*[]int,c-chan-int,done-chan-bool){
对于len(*列表)!=0{
结果:=(*列表)[0]
*列表=(*list)[1:]
fmt.Println(“即将发送”,结果)
c代码有很多问题,让我们看看
您的pop
函数在访问切片时不会锁定,因此这就是数据竞争
for len(list)>0{}
是一种数据竞争,因为您在其他两个goroutine中修改列表时正在访问列表
for len(list)>0{}
将永远不会返回,因为您的列表中有3项,但您只调用了两次pop
receiver(c)
由于#3的错误,它尝试从通道读取数据,但没有写入数据
一种方法是使用一个编写器(pop
)和多个读卡器(receiver
):
func-pop(列表*[]int,c-chan-int,done-chan-bool){
对于len(*列表)!=0{
结果:=(*列表)[0]
*列表=(*list)[1:]
fmt.Println(“即将发送”,结果)
c请在代码上运行“go fmt”,这样我们更容易阅读。如果你发布一个完全有效的示例,我们甚至可以将其复制并粘贴到我们的编辑器中并使用它。很抱歉,上次有人编辑了我的代码,只留下了函数。我将添加到PlayGround的链接。请在代码上运行“go fmt”,这样我们就更容易了o阅读它。如果你发布了一个完全有效的示例,我们甚至可以将其复制粘贴到我们的编辑器中并使用它。很抱歉,上次有人编辑了我的代码,只留下了一些函数。我将添加一个指向操场+1的链接,尽管-race
没有检测到所有内容()+1,尽管-race
没有检测到所有内容()
func pop(list *[]int, c chan int) {
if len(*list) != 0 {
result := (*list)[0]
*list = (*list)[1:]
fmt.Println("about to send ", result)
c <- result
} else {
return
}
}
func receiver(c chan int) {
result := <-c
fmt.Println("received ", result)
}
var list = []int{1, 2, 3}
func main() {
fmt.Println("Main")
c := make(chan int)
go pop(&list, c)
go pop(&list, c)
for len(list) > 0 {
receiver(c)
}
close(c) //Dosen't seem to have any effect
fmt.Println("done")
}
func pop(list *[]int, c chan int, done chan bool) {
for len(*list) != 0 {
result := (*list)[0]
*list = (*list)[1:]
fmt.Println("about to send ", result)
c <- result
}
close(c)
done <- true
}
func receiver(c chan int) {
for result := range c {
fmt.Println("received ", result)
}
}
var list = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
func main() {
c := make(chan int)
done := make(chan bool)
go pop(&list, c, done)
go receiver(c)
go receiver(c)
go receiver(c)
<-done
fmt.Println("done")
}