3

我很难理解缓冲通道是如何工作的。基于以下示例,我尝试一次使用 2 个线程来打印当前时间,每 2 个 go 调用之间大约有 2 秒的延迟:

package main
import "fmt"
import "time"

func main() {
    returnCurrentTime := func() string  {
        return time.Now().String()
    }

    c := make(chan string, 2)

    asyncReturnCurrentTime := func(c chan string) {
        time.Sleep(2001 * time.Millisecond)
        c <- returnCurrentTime()
    }

    for i := 1; i != 7; i++ {
        go asyncReturnCurrentTime(c)
        if(i % 3 == 0) {
            fmt.Println(<- c)
            fmt.Println(<- c)
            fmt.Println(<- c)
            fmt.Println()
        }
    }
}

这产生

2013-02-27 03:17:50
2013-02-27 03:17:50
2013-02-27 03:17:50

2013-02-27 03:17:52
2013-02-27 03:17:52
2013-02-27 03:17:52

我对秒数的期望是两次 go 调用之间的 2 秒延迟,在这种情况下,结果如下

2013-02-27 03:17:50
2013-02-27 03:17:50
2013-02-27 03:17:52 <- 3rd call with 2 buffer slots

2013-02-27 03:17:54
2013-02-27 03:17:54
2013-02-27 03:17:56 <- 3rd call with 2 buffer slots

显然我误解了缓冲通道的概念,请有人解释一下我的逻辑错误以及如何达到预期的结果?

谢谢

4

1 回答 1

3

实际上,您正在运行:

package main

import (
    "fmt"
    "time"
)

func main() {
    returnCurrentTime := func() string {
        return time.Now().String()
    }

    c := make(chan string, 2)

    asyncReturnCurrentTime := func(c chan string) {
        time.Sleep(2001 * time.Millisecond)
        c <- returnCurrentTime()
    }

    go asyncReturnCurrentTime(c)
    go asyncReturnCurrentTime(c)
    go asyncReturnCurrentTime(c)
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println()
    go asyncReturnCurrentTime(c)
    go asyncReturnCurrentTime(c)
    go asyncReturnCurrentTime(c)
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println()
}

输出:

2013-02-26 21:28:22.069581655 -0500 EST
2013-02-26 21:28:22.069688722 -0500 EST
2013-02-26 21:28:22.069695217 -0500 EST

2013-02-26 21:28:24.070985411 -0500 EST
2013-02-26 21:28:24.070999309 -0500 EST
2013-02-26 21:28:24.071002661 -0500 EST

发送报表

通道和值表达式都在通信开始之前进行评估。通信阻塞,直到发送可以继续。

returnCurrentTime()尝试发送之前,立即评估表达式(时间戳)。这不是发送的时间戳。如果缓冲区已满,发送可能会在稍后发生。

此外,测量实际发送和接收时间,缓冲延迟chan c将是无关紧要的:发送、发送、阻塞、接收、解除阻塞、发送。例如,

c <-;  2013-02-26 23:29:34.505456624 -0500 EST
c <-;  2013-02-26 23:29:34.505467030 -0500 EST
<- c;  2013-02-26 23:29:34.505468497 -0500 EST
c <-;  2013-02-26 23:29:34.505518015 -0500 EST

c <-;  2013-02-26 23:31:36.506659943 -0500 EST
c <-;  2013-02-26 23:31:36.506664832 -0500 EST
<- c;  2013-02-26 23:31:36.506669302 -0500 EST
c <-;  2013-02-26 23:31:36.506696540 -0500 EST
于 2013-02-27T02:29:54.020 回答