2 回答

TA贡献1963条经验 获得超6个赞
我想了解通道的解剖结构,我制作的代码几乎与您制作的代码相同。我对您的代码进行了一些小的更改
func main() {
runtime.GOMAXPROCS(1)
done := make(chan int, 2)
count := 4
go func() {
defer close(done)
for i := 0; i < count; i++ {
done <- i
fmt.Println("AAAAAAAA", i)
}
}()
for j := 0; j < count; j++ {
i, ok := <-done
if !ok {
break
}
fmt.Println("BBBBBBBBBB", i)
}
time.Sleep(1 * time.Millisecond)
}
现在,输出将是这样的
AAAAAAAA 0
AAAAAAAA 1
AAAAAAAA 2
BBBBBBBBBB 0
BBBBBBBBBB 1
BBBBBBBBBB 2
BBBBBBBBBB 3
AAAAAAAA 3
我在Cox-Buday,Katherine的并发书中发现了有关此内容的有趣信息。
还值得一提的是,如果缓冲通道为空并且具有接收器,则缓冲区将被绕过,并且值将直接从发送方传递到接收器。
根据这些信息,我的理解是,当我们有一个容量为2的缓冲通道时:
-> main goroutine is blocked, because the channel is empty
AAAAAAAA 0 -> because, there is an active receiver this value bypassed the channel
AAAAAAAA 1 -> this value is the first value in the channel
AAAAAAAA 2 -> this value is the second value in the channel and channel is full now, so this goroutine is blocked
BBBBBBBBBB 0 -> the main goroutine can unblock now and read the "bypassed" value
-> i think the anonymous goroutine can pass the third value to channel somewhere i here
BBBBBBBBBB 1 -> the main goroutine reads the first value from the channel
BBBBBBBBBB 2 -> the main goroutine reads the second value from the channel
BBBBBBBBBB 3 -> the main goroutine reads the third value
-> the main goroutine blocked by sleep
AAAAAAAA 3 -> the anonymous goroutine can run the print statement
我不是100%确定这种情况会发生,但这是我的观察。无缓冲通道也是缓冲通道,但具有 0(或 1)容量。如果您尝试使用0(无缓冲)容量的代码,这也很有趣。结果将如下所示:
AAAAAAAA 0
BBBBBBBBBB 0
BBBBBBBBBB 1
AAAAAAAA 1
AAAAAAAA 2
BBBBBBBBBB 2
BBBBBBBBBB 3
AAAAAAAA 3
最后,这是我的代码。我使用缓冲区来存储结果,并仅在 main 函数的末尾将其写出到 stdout。
func main() {
runtime.GOMAXPROCS(1)
var stdoutBuff bytes.Buffer
defer stdoutBuff.WriteTo(os.Stdout)
intStream := make(chan int, 0)
go func() {
defer close(intStream)
defer fmt.Fprintln(&stdoutBuff, "Producer done.")
for i := 0; i < 5; i++ {
fmt.Fprintf(&stdoutBuff, "Before Sending: %d\n", i)
intStream <- i
fmt.Fprintf(&stdoutBuff, "After Sending: %d\n", i)
}
}()
// for integer := range intStream {
// fmt.Fprintf(&stdoutBuff, "Received: %v\n", integer)
// }
for {
fmt.Fprintf(&stdoutBuff, "Before received.\n")
v, ok := <-intStream
if !ok {
break
}
fmt.Fprintf(&stdoutBuff, "Received: %v\n", v)
}
}
我希望它能有所帮助。
- 2 回答
- 0 关注
- 115 浏览
添加回答
举报