【问题标题】:Return after channel ends parent routine通道结束父例程后返回
【发布时间】:2018-03-01 05:41:42
【问题描述】:

我在下面有一段运行 go 例程的 main 的代码摘录。为什么这不会发生:主进程在收到完成后和作业返回之前退出,这会使子进程变得僵尸。任何对 golang 文档的参考都会有所帮助。

func main() {
    var jobDone = make(chan bool)
    go job(jobDone)
    <-jobDone
}

func job(done chan bool) {
    for {
        select {
        case <-someOtherGlobalChannel:
            //Please ignore this case/channel
            fmt.Println("SOmeOtherChannel received")
        default:
            if check_somthing_expression {
                done <- true
                return
            }
        }
    }
}

【问题讨论】:

  • &lt;-done 中的job 将导致死锁,因为该通道没有发送者。
  • 一方面,没有子进程。
  • @vedhavyas 是的,我同意。我的不好,我匆忙把我的代码总结成上面的代码。

标签: go concurrency


【解决方案1】:

通过这些更改,您的主频道将在完成频道后退出

package main

import (
    "fmt"
)

func main() {
    var jobDone = make(chan bool)
    go job(jobDone)
    <-jobDone
}

func job(done chan bool) {
    for {
        select {
        case <-someOtherGlobalChannel:
            //Please ignore this case/channel
            fmt.Println("SOmeOtherChannel received")
        default:
            if check_somthing_expression {
                done <- true
                return
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    僵尸进程

    "...这会使子进程变成僵尸"

    go job() 不会启动一个单独的进程,它会启动另一个 goroutine。在这个程序中有一个 main goroutine 和一个 job goroutine。 Language spec:

    “go”语句在同一地址空间内以独立并发控制线程或 goroutine 的形式开始执行函数调用。

    因此,您不会创建 Unix 僵尸进程。

    主程序在作业之前未退出

    “为什么不会发生这种情况:主程序在收到完成后和作业返回之前退出......?”

    原因 #1:接收操作阻塞了两个 Goroutines

    (1) 因为在job 的频道done 上没有发送语句。

    <-done
    

    是一个接收操作。见"Receive operator" in Go spec:

    对于通道类型的操作数ch,接收操作&lt;-ch的值是从通道ch接收到的值。

    另见"Send statements" in Go spec

    ch &lt;- 3 // send value 3 to channel ch

    您需要一个发送语句。例如:

    done <- true
    

    the Go TourEffective Go 中提供了更多解释性文本和示例。

    ...还有第二个原因:

    原因 #2:发送和返回之间没有任何关系

    (2) 因为,即使你将接收操作更改为发送语句,job goroutine 在它在通道上发送和返回之间也没有什么可做的,所以任何时候都不太可能从一个传递到下一个。如果您希望这种情况发生,请使用 time package 添加睡眠作业:

    done <- true
    time.Sleep(time.Second * 30)
    return
    

    【讨论】:

      【解决方案3】:

      你需要在你的done频道里放一些bool消息,然后<-jobDone }可以得到一些消息来完成这个块

      【讨论】:

      • 是的,我同意。我的不好,我匆忙把我的代码总结成上面的代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 2015-08-08
      • 2019-03-25
      • 1970-01-01
      相关资源
      最近更新 更多