Go 从频道阅读

Go 从频道阅读,go,concurrency,Go,Concurrency,在阅读Go中的频道时,我发现发布功能和消费功能之间并没有完全同步。奇怪的是,若这是CPU调度的一个怪癖,我会在某些时候得到不同的结果。main中的消费者似乎一次消费两倍并打印它们 考虑以下示例: 主程序包 进口( “fmt” ) func平方(ch chan int){ 对于i:=0;i您使用的是无缓冲通道,因此会发生这种情况 注:这不是技术上100%准确的描述 主例程启动。它运行到val:=range c{的。然后它被置于“睡眠”状态,因为没有可从c读取的值 刚刚创建的squares的goro

在阅读Go中的频道时,我发现发布功能和消费功能之间并没有完全同步。奇怪的是,若这是CPU调度的一个怪癖,我会在某些时候得到不同的结果。
main
中的消费者似乎一次消费两倍并打印它们

考虑以下示例:

主程序包
进口(
“fmt”
)
func平方(ch chan int){

对于i:=0;i您使用的是无缓冲通道,因此会发生这种情况

注:这不是技术上100%准确的描述

  • 主例程启动。它运行到val:=range c{
  • 。然后它被置于“睡眠”状态,因为没有可从c读取的值
    
  • 刚刚创建的
    squares
    的goroutine正在“唤醒”。它创建了一个值,可以在另一个goroutine已经“等待”频道上的值时发布。然后它创建了另一个值,无法在频道现在阻塞时发布
  • 主例程是“awoken”,读取值,打印它,读取另一个goroutine已经等待推送的下一个值。打印它,然后由于没有新值可用而再次被卡住
  • sqares
    的goroutine被“唤醒”,因为它能够推送它的值。它打印“发布后”,创建一个新值,发布它,因为另一个例程已经在等待一个值,然后创建另一个。然后它被卡住,因为另一个例程没有准备好接收下一个值
  • 回到第3页)
  • 如果您想要一个“更平滑”的工作流,其中例程不会对通过通道的每个值进行同步,请创建一个缓冲通道:

    c:=make(chan int,3)
    
    你的问题是什么?这个输出非常好。同步发生在实际的通道操作上。打印语句不同步,它们只在各自的go例程中的操作序列中排序。如果我想要完全同步,该怎么办?
    created val 0 
    After posting val 0 
    created val 1 
    0
    1
    After posting val 1 
    created val 4 
    After posting val 4 
    created val 9 
    4
    9
    After posting val 9 
    created val 16 
    After posting val 16 
    created val 25 
    16
    25
    After posting val 25 
    created val 36 
    After posting val 36 
    created val 49 
    36
    49
    After posting val 49 
    created val 64 
    After posting val 64 
    64
    
    created val 0 
    0
    After posting val 0 
    ...