2013-02-27 150 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