golang 中的生产者消费者
producer consumer in golang
尝试运行使用下面的代码(生产者和消费者)来理解 golang 中的 goroutines 和通道(从下面的代码片段中删除了包和导入):
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() 时,执行 2 个 goroutines 的 运行time kicks(java 世界中的线程排序,但不是实际的 OS 线程) 和 main() goroutine 出现并停止在“<-done”。
现在在 produce() 内部——循环从 0 到 9,在循环内部,msgs 通道一次接收 int (0 到 9) 1,该时间由 consume() 并行消耗;但是 produce 对此一无所知,它只是一直循环 0 到 9。
问题:假设我的上述理解是正确的。有一次,for 循环完成了,为什么 produce() 中的下一个 printLine 没有被打印出来,为什么 msgs 通道没有被关闭?为什么 goroutine 在 produce() 内部停止,直到消费者消耗完所有消息?
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
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{}{}
}
尝试运行使用下面的代码(生产者和消费者)来理解 golang 中的 goroutines 和通道(从下面的代码片段中删除了包和导入):
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() 时,执行 2 个 goroutines 的 运行time kicks(java 世界中的线程排序,但不是实际的 OS 线程) 和 main() goroutine 出现并停止在“<-done”。 现在在 produce() 内部——循环从 0 到 9,在循环内部,msgs 通道一次接收 int (0 到 9) 1,该时间由 consume() 并行消耗;但是 produce 对此一无所知,它只是一直循环 0 到 9。
问题:假设我的上述理解是正确的。有一次,for 循环完成了,为什么 produce() 中的下一个 printLine 没有被打印出来,为什么 msgs 通道没有被关闭?为什么 goroutine 在 produce() 内部停止,直到消费者消耗完所有消息?
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
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{}{}
}