go - golang 中的生产者消费者

标签 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 和 channel 的理解: 当我们使用 go 关键字从 main() 调用 produce() 和 consume() 时,go 运行时启动了 2 个 goroutines(Java 世界中的某种线程,但不是实际的 OS 线程)并且 main() goroutine 出现并停止在“< -完毕”。 现在在 produce() 内部——循环从 0 到 9,在循环内部,msgs channel 一次接收 int (0 到 9) 1,该时间由 consume() 并行消耗;然而 produce 对此一无所知,它只是一直循环 0 到 9。

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

最佳答案

msgs channel 是无缓冲的。这意味着要完成发送,必须有一个相应的接收操作也可以完成。这提供了 goroutine 之间的同步点。

如果您只是在示例中再添加一些打印语句,就很容易看出

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

关于go - golang 中的生产者消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29634649/

相关文章:

go - 在 Go 中包装多个实现

go - 如何理解goroutine的这种行为?

go - 上下文取消不退出

mongodb - 在go中使用和分配其他文件(包)的变量

go - 我如何在 goloang ssh session 中捕获交错的 stdout 和 stderr?

go - 检索后无法将数据插入数据库

multithreading - 为什么我的 goroutines 在完成时互相等待而不是完成?

go - 获取绑定(bind) : address already in use even after closing the connection in golang

go - 带有 channel 的Goroutine的行为

hash - Go, midstate SHA-256 哈希