一开始卡了很久,之前玩过生产者---消费者模型,但是一对一的,遇到1对2的模型,就毫无头绪了,一开始写的造成了死锁或者死循环,甚至造成电脑死机,卡了一个小时,终于想明白了如何解决,说到底还是对channel机制不够了解,
1个生产者,两个消费者,可以先定义如下比较简单的场景:
1.生产者生产完数据,比如10个int类型数据
2.生产完后再由消费者取出
要想实现这个方案要解决几个问题:
1.怎么确保生产者生产结束前不被消费者干扰,因为边存边取的话,实现起来比较复杂
2.怎么确保消费者能够顺利取走所有数据,取走数据后程序正常退出
3.
4.避免死锁等问题
解决方案如下:
1.生产者放在主协程,数据存入缓冲通道product,程序是串行运行,即自上而下,协程虽然会打乱顺序,但对于其之前的,除非之前的程序阻塞,不然不会发生抢占
2.由于数据放在缓冲通道,所以就变成将缓冲通道读取完毕,读取完之后,通道为空,即len(product)=0
另外,利用无缓冲通道,把好最后一道关,将其放在靠后的位置,阻塞整个主协程,让消费者协程有时间输出数据,并且消费者在取完数据就立即通知该channel,我取完了
3.死锁问题,主要是注意避免读取空的channel,所以,要想避免死锁,得及时关闭channelm,这里多指有缓冲的,无缓冲的有他的使命
package main
import (
"fmt"
)
var(
product = make(chan int,10)
isClosed bool
hasNoProduct =make(chan bool)
)
func main(){
for i:=0;i<10;i++{
product<-i
fmt.Println("produce:",i)
}
close(product)
go customerA()
go customerB()
<-hasNoProduct
defer close(hasNoProduct)
}
func customerA(){
for i:=0;i<5;i++{
fmt.Println("customer A:",<-product)
}
if len(product)==0&&!isClosed{
hasNoProduct<-true
}
}
func customerB(){
for i:=0;i<5;i++{
fmt.Println("customer B:",<-product)
}
if len(product)==0&&!isClosed{
hasNoProduct<-true
}
}