无缓冲信道无法同步工作

我对GoLang世界很陌生,并且正在尝试goroutines/频道。据我所知,渠道是戈鲁丁之间的双向沟通方式。如果我们创建一个长度为 0 的通道,它应该是一个同步通道,它表示除非某些 goroutine(即使用者)从通道读取值,否则生产者将无法前进。


我尝试了下面的示例来测试这一点,但我没有得到预期的结果。


package main


import (

    "fmt"

    "time"

)


var done = make(chan bool)

var msgs = make(chan int)


func produce() {

    for i := 0; i < 40; i++ {

        //fmt.Println("sending")

        fmt.Println("Produced: ", i)

        msgs <- i

        //fmt.Println("Channel size is: ", len(msgs))

    }

    fmt.Println("Before closing channel")

    close(msgs)

    fmt.Println("Before passing true to done")

    


}


func consume() {

    for msg := range msgs {

        //fmt.Println("Going to take one, Channel size is: ", len(msgs))

        fmt.Println("Consumer: ", msg)

        time.Sleep(100 * time.Millisecond)


    }

    done <- true

    

}


func main() {

    go produce()

    go consume()

    <-done

    fmt.Println("After calling DONE")

}


输出:


Produced:  0

Produced:  1

Consumer:  0

Consumer:  1

Produced:  2

Consumer:  2

...

我期望输出


Produced:  0

Consumer:  0

Produced:  1

Consumer:  1

Produced:  2

Consumer:  2

请帮我在这里指出我做错了什么?


素胚勾勒不出你
浏览 76回答 1
1回答

子衿沉夜

(无缓冲)通道读取/写入将按照您期望的顺序进行:一次写入;一读;一写;一次阅读等。但是,生产者/消费者 goroutines 中的调用是不同步的 - 因此,生产者可以在 之前将其功能放入调度程序中。fmt.Printlnfmt.Printlnconsumer由于睡眠 - 它自愿向调度程序提供提示,让其他goroutines跑在它前面。因此,最有可能总是在醒来之前进行第二次运行。consumerproducerfmt.Printlnconsumer如果你把睡眠移到gooutine,你可以看到你在操场上的预期行为:https://play.golang.org/p/5x9_yyUaMiJ&nbsp;- 但是你不应该依赖这些计时技巧。如果要确保一个函数相对于另一个 goroutine 的执行顺序,这些任务也必须同步。通过通道读取/写入 - 只有读取/写入保证是安全的和顺序的。producer
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go