2013-02-27 151 views
3

我很难理解缓冲通道的工作原理。基于下面的例子中,我试图利用2个线程同时打印出当前时间,大约有2第二延迟每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 

什么我期待关于秒是有史以来二去电话产生以下结果

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 

显然我误解缓冲瓒的概念之间,在这种情况下,2个第二延迟nels,请有人请我解释我的逻辑中的错误,以及如何达到预期的结果?

谢谢

+0

您有更多的两个“线程”。在这种情况下,每个例程都像一个线程一样工作,所以在某一时刻,您正在运行三个例程加上主线程,这样就有四个“线程”。 – masebase 2013-02-27 02:54:23

回答

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 

Send statements

两个通道和值表达式0123之前评估沟通开始。通信阻塞,直到发送可以继续。

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 
+0

在接收之前,通道缓冲区限制“2”不应该限制为2个最大呼叫吗?如果不是,缓冲限制的要点是什么? – Dante 2013-02-27 02:39:04

+0

您需要准确理解您的时间戳记代表什么。看到我修改后的答案。 – peterSO 2013-02-27 03:07:21