为了账号安全,请及时绑定邮箱和手机立即绑定

你能告诉我golang通道缓冲器是如何工作的吗?

你能告诉我golang通道缓冲器是如何工作的吗?

Go
杨魅力 2022-08-24 17:36:11
为什么剂量不工作缓冲液到右边的golang上?如果通道已满,则等待。这是错的吗?我不明白它是如何工作的。你能告诉我golang通道缓冲器是如何工作的吗?import (    "fmt"    "runtime");func main() {    runtime.GOMAXPROCS(1);     done := make(chan bool, 2);     count := 4;    go func() {        for i := 0; i < count; i++ {            done <- true            fmt.Println("AAAAAAAA", i);        }    }()    for j := 0; j < count; j++ {        <-done        fmt.Println("BBBBBBBBBB", j);    }}---------------------------------------------------------------------------------AAAAAAAAAAAAAAA 0AAAAAAAAAAAAAAA 1AAAAAAAAAAAAAAA 2BBBBBBBBBB 0BBBBBBBBBB 1BBBBBBBBBB 2BBBBBBBBBB 3这是我的期望AAAAAAAAAAAAAAA 0AAAAAAAAAAAAAAA 1BBBBBBBBBB 0BBBBBBBBBB 1AAAAAAAAAAAAAAA 2AAAAAAAAAAAAAAA 3BBBBBBBBBB 2BBBBBBBBBB 3
查看完整描述

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)

    }

}

我希望它能有所帮助。


查看完整回答
反对 回复 2022-08-24
?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

仅当 Go 无法在下一个项目到达之前处理一个项目时,通道缓冲区才会填满。在您的情况下,没有积压的项目,因为每个项目都可以快速有效地处理。


查看完整回答
反对 回复 2022-08-24
  • 2 回答
  • 0 关注
  • 115 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号