英文:
Require help in understanding buffered channels
问题
我很难理解缓冲通道的工作原理。根据以下示例,我正在尝试同时利用两个线程打印出当前时间,每两个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 <- 第3次调用,有2个缓冲槽
2013-02-27 03:17:54
2013-02-27 03:17:54
2013-02-27 03:17:56 <- 第3次调用,有2个缓冲槽
显然,我误解了缓冲通道的概念,请问有人能够友好地解释我的逻辑错误以及如何实现预期的结果吗?
谢谢
英文:
I'm having a hard time understanding how buffered channels work. Based on the following example, i'm trying to utilize 2 threads at a time to print out the current time, with approximately 2 second delays between every 2 go calls:
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()
}
}
}
This produces
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
What i'm expecting regarding the seconds is 2 second delays between ever 2 go calls and in this case the following result
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
Obviously i misunderstood the concept of buffered channels, would somebody please be kind enough to explain the fault in my logic and how to achieve the expected result?
Thank you
答案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
英文:
Effectively, you are running:
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()
}
Output:
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
>
> Both the channel and the value expression are evaluated before
> communication begins. Communication blocks until the send can proceed.
The returnCurrentTime()
expression (the timestamp) is evaluated immediately, before an attempt is made to send. It's not a timestamp for the send. The send may happen later if the buffer is full.
Also, measuring actual send and receive times, the buffering delay for chan c
is going to be inconsequential: send, send, block, receive, unblock, send. For example,
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论