Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 即使通道关闭,go例程也会死锁_Concurrency_Go_Goroutine - Fatal编程技术网

Concurrency 即使通道关闭,go例程也会死锁

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

我有一个列表,有一个函数从中弹出元素,还有一个函数“接收”弹出的元素。我原以为在接收器之后关闭会关闭通道,但似乎程序在到达那里之前就死锁了。这样做的最佳方式是什么?我是否应该有另一个频道来检测pop何时完成

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")
    }