去频道:一个额外线的功能

时间:2014-09-30 07:52:49

标签: go

我正在学习Go中的并发模式,不确定Point A的目的是什么?

代码取自:https://talks.golang.org/2012/concurrency.slide#30

任何人都可以向我解释一下吗?感谢

type Message struct {
    str  string
    wait chan bool
}

func main() {
    c := fanIn(boring("Joe"), boring("Ann"))
    for i := 0; i < 5; i++ {
        msg1 := <-c
        fmt.Println(msg1.str)
        msg2 := <-c
        fmt.Println(msg2.str)
        msg1.wait <- true
        msg2.wait <- true
    }
    fmt.Println("You're both boring; I'm leaving.")
}

func fanIn(input1, input2 <-chan Message) <-chan Message {
    c := make(chan Message)
    go func() {
        for {
            c <- <-input1
        }
    }()
    go func() {
        for {
            c <- <-input2
        }
    }()
    return c
}

func boring(msg string) <-chan Message { 
    waitForIt := make(chan bool)
    c := make(chan Message)
    go func() { // We launch the goroutine from inside the function.
        for i := 0; ; i++ {
            c <- Message{fmt.Sprintf("%s %d", msg, i), waitForIt}
            time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond)
            <-waitForIt                          // <-----------------Point A
        }
    }()
    return c // Return the channel to the caller.
}

3 个答案:

答案 0 :(得分:2)

fanIn产生两个goroutines,从第一个和第二个&#34;无聊&#34;消息信道。由于两个goroutine都可能正在运行(另一个正在运行或正在运行),我们不知道元素被写入统一通道的顺序:

A A A A A \
            > A B B A A A B A B B
B B B B B /

请注意,生成的序列没有特定的顺序。

这可以通过commenting out the "waiting"-channels来证明:

Joe 0
Ann 0
Joe 1
Ann 1
Joe 2
Ann 2
Joe 3
Joe 4
Joe 5
Ann 3
You're both boring; I'm leaving.

等待通道存在以恢复序列,因为您链接的幻灯片说。我们想要这个:

A A A A A \
            > A B A B A B A B A B
B B B B B /

请注意Ann和Joe talk one after the other now

Joe 0
Ann 0
Joe 1
Ann 1
Joe 2
Ann 2
Joe 3
Ann 3
Joe 4
Ann 4
You're both boring; I'm leaving.

这段代码的作者决定通过让他们等待waitForIt并在main中通知来同步写入通道。此行为依赖于我们在main&#39; s for中获得的前两条消息 - 循环有序。如果不是,我们就会得到相反的序列。

也许我没有看到任何更多的绝对同步保证,也许作者不关心序列的顺序,只要它是一个重复的序列,但这段代码不会让我感觉不到特别好的并发和同步示例。

答案 1 :(得分:1)

整个演示文稿可在YouTube找到。大约8分钟,它将更接近你的问题。 Rob Pike解释了一切,但(这也是tomwilde所说的)演示中的例子缩小到只让观众看到最重要的东西。后来在演讲中,&#34;无聊&#34;将被&#34;有趣的&#34;取代。这将使Rob更加清楚地尝试解释。

答案 2 :(得分:0)

由于wait频道每次只能包含一个元素,因此PointA只是通过阻止goroutine来确保没有人会继续。然后他将卸载&#34;按顺序通道,允许例程继续