golang的生产者消费者

时间:2015-04-14 18:18:58

标签: go goroutine

尝试运行以下代码(生产者和消费者)来了解golang中的goroutines和channel(从下面的代码片段中删除包和导入):

var done = make(chan bool)
var msgs = make(chan int)

func produce() {
    for i := 0; i < 10; i++ {
            msgs <- i
    }
    fmt.Println("Before closing channel")
    close(msgs)
    fmt.Println("Before passing true to done")
    done <- true
}

func consume() {
    for {
            msg := <-msgs
            time.Sleep(100 * time.Millisecond)
            fmt.Println("Consumer: ", msg)
    }
}

func main() {
    go produce()
    go consume()
    <-done
    fmt.Println("After calling DONE")
}

源代码来自:http://www.golangpatterns.info/concurrency/producer-consumer

以下是运行代码时的输出

Consumer:  0
Consumer:  1
Consumer:  2
Consumer:  3
Consumer:  4
Consumer:  5
Consumer:  6
Consumer:  7
Consumer:  8
Before closing channel
Before passing true to done
After calling DONE

基于我对goroutines和频道的理解: 当我们使用go关键字从main()调用produce()和consume()时,运行2个goroutines(java世界中的线程而不是实际的OS线程),并且main()goroutine在&#停止34;&LT;完成度的数&#34 ;. 现在在produce()中 - 循环从0到9并且在循环内部,msgs通道一次接收int(0到9)1,并且被consume()并行消耗;但是产品对它没有任何线索,它只是保持循环0到9.

问题:假设我的上述理解是正确的。有一次,fo​​r循环完成,为什么yield()中的下一个printLine没有被打印,为什么msgs通道没有被关闭?为什么goroutine停止在produce()中,直到消费者消耗掉所有的消息?

2 个答案:

答案 0 :(得分:2)

msgs频道未缓冲。这意味着对于发送完成,必须有相应的接收操作,也可以完成。这提供了goroutines之间的同步点。

如果您只是在示例中添加一些打印语句

,很容易看到

http://play.golang.org/p/diYQGN-iwE

func produce() {
    for i := 0; i < 4; i++ {
        fmt.Println("sending")
        msgs <- i
        fmt.Println("sent")
    }
    fmt.Println("Before closing channel")
    close(msgs)
    fmt.Println("Before passing true to done")
    done <- true
}

func consume() {
    for msg := range msgs {
        fmt.Println("Consumer: ", msg)
        time.Sleep(100 * time.Millisecond)

    }
}

输出:

sending
Consumer:  0
sent
sending
Consumer:  1
sent
sending
Consumer:  2
sent
sending
Consumer:  3
sent
Before closing channel
Before passing true to done
After calling DONE

答案 1 :(得分:0)

package main

import (
    "fmt"
)

var ch chan int
var ch1 chan struct{}

func main() {
    ch = make(chan int)
    ch1 = make(chan struct{})
    go producer()
    go consumer()
    <-ch1
    close(ch)
    close(ch1)
}

func consumer() {
    for {
        fmt.Println("number", <-ch)
    }
}
func producer() {
    for i := 0; i < 10; i++ {
        ch <- i
    }
    ch1 <- struct{}{}
}