【问题标题】:How to make this Go code print in 3 seconds?如何在 3 秒内打印出这个 Go 代码?
【发布时间】:2020-12-08 15:09:37
【问题描述】:

这是 Go 代码 https://www.intervue.io/sandbox-ILSCXZ6RR

func worker() chan int {
   ch := make(chan int)

   go func() {
      time.Sleep(3 * time.Second)
      ch <- 42
   }()

   return ch
}

func main() {
   timeStart := time.Now()

   _, _ = <-worker(), <-worker()

   println(int(time.Since(timeStart).Seconds())) // 3 or 6 ?
}

我怎样才能让它在 3 秒内执行而不是在 6 秒内执行?

【问题讨论】:

  • 代码在 6 秒内运行,因为你运行了两次 worker。 3+3 = 6s

标签: go time concurrency channel goroutine


【解决方案1】:

因为你是从worker()返回的频道接收,所以需要6秒,所以第二个worker()不能启动,直到从第一个接收到一个值,这需要3秒。

您正在使用元组赋值。 Spec: Assignments:

任务分两个阶段进行。首先,左边的index expressionspointer indirections的操作数(包括selectors中的隐式指针间接)和右边的表达式都是evaluated in the usual order。其次,作业是按从左到右的顺序进行的。

还有Spec: Order of evaluation:

...在计算表达式、赋值或return statementoperands 时,所有函数调用、方法调用和按词法从左到右的顺序计算通信操作 .

先启动 2 个 worker,然后然后从通道中接收,这样 goroutine 才能真正并发运行:

ch1, ch2 := worker(), worker()
_, _ = <-ch1, <-ch2

这样,输出将是(在Go Playground 上尝试):

3

【讨论】:

    【解决方案2】:

    你也可以删除频道,因为你没有使用频道的结果,只需使用 sync.WaitGroup

    func worker(n int, wg *sync.WaitGroup) {
        defer wg.Done()
        time.Sleep(3 * time.Second)
        fmt.Println("done")
    }
    
    func main() {
        timeStart := time.Now()
        var wg sync.WaitGroup
    
        for i := 0; i <= 1; i++ {
            wg.Add(1)
            go worker(i, &wg)
        }
        wg.Wait()
    
        fmt.Println(int(time.Since(timeStart).Seconds())) // 3
    }
    

    这里是示例代码:https://play.golang.org/p/9_Ymx0tcHqS

    【讨论】:

    • 重点不是简化应用程序,因为 3 秒睡眠和println(3) 将等同于所需的应用程序。关键是要了解为什么原始应用没有在 3 秒内完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2021-06-27
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    相关资源
    最近更新 更多