Go实现生产者消费者模型
基于同步锁实现
import (
"fmt"
"sync"
)
var (
productCount = 5
mutex sync.Mutex
cond = sync.NewCond(&mutex)
)
type producer struct {
}
func (r *producer) produce() {
for {
cond.L.Lock()
if productCount < 10 {
productCount++
fmt.Printf("生产者生产了一个产品,当前存量%d\n", productCount)
} else {
fmt.Printf("仓库满了,当前容量%d\n", productCount)
cond.Wait()
}
cond.L.Unlock()
cond.Broadcast()
}
}
func (r *consumer) consumer() {
for {
cond.L.Lock()
if productCount > 0 {
productCount--
fmt.Printf("消费者消费了一个产品,当前存量%d\n", productCount)
} else {
fmt.Printf("仓库空了,当前存量%d\n", productCount)
cond.Wait()
}
cond.L.Unlock()
cond.Broadcast()
}
}
type consumer struct {
}
func main() {
var p = producer{}
var c = consumer{}
go p.produce()
go c.consumer()
}
然而实际什么都没有输出,这是因为生产者消费者执行方法时主线程已经结束了,给主线程加个时延
func main() {
var p = producer{}
var c = consumer{}
go p.produce()
go c.consumer()
time.Sleep(time.Microsecond * 10)
}
基于通道实现
基于通道实现的这种方式需要注意避免从空通道中取数,否则就会出现死锁
var countChan chan int
type producer struct {
}
func (r *producer) produce() {
for i := 0; i < 10; i++ {
count := <-countChan
if count < 10 {
count++
fmt.Printf("生产者生产了一个产品,当前存量%d\n", count)
} else {
fmt.Printf("仓库满了,当前容量%d\n", count)
}
countChan <- count
var t = rand.Intn(100)
time.Sleep(time.Duration(t))
}
}
func (r *consumer) consumer() {
for i := 0; i < 10; i++ {
count := <-countChan
if count > 0 {
count--
fmt.Printf("消费者消费了一个产品,当前存量%d\n", count)
} else {
fmt.Printf("仓库空了,当前存量%d\n", count)
}
countChan <- count
var t = rand.Intn(100)
time.Sleep(time.Duration(t))
}
}
type consumer struct {
}
func main() {
countChan = make(chan int, 1)
countChan <- 0
var p = producer{}
var c = consumer{}
go p.produce()
go c.consumer()
time.Sleep(1000)
}
基于select解决通道阻塞问题
import (
"fmt"
"math/rand"
"time"
)
var countChan chan int
type producer struct {
}
func (r *producer) produce() {
for i := 0; i < 10; i++ {
select {
case count := <-countChan:
if count < 10 {
count++
fmt.Printf("生产者生产了一个产品,当前存量%d\n", count)
} else {
fmt.Printf("仓库满了,当前容量%d\n", count)
}
countChan <- count
var t = rand.Intn(100)
time.Sleep(time.Duration(t))
default:
fmt.Println("初始化产品池")
countChan <- 0
}
}
}
func (r *consumer) consumer() {
for i := 0; i < 10; i++ {
select {
case count := <-countChan:
if count > 0 {
count--
fmt.Printf("消费者消费了一个产品,当前存量%d\n", count)
} else {
fmt.Printf("仓库空了,当前存量%d\n", count)
}
countChan <- count
var t = rand.Intn(100)
time.Sleep(time.Duration(t))
default:
fmt.Println("初始化产品池")
countChan <- 0
}
}
}
type consumer struct {
}
func main() {
countChan = make(chan int, 1)
var p = producer{}
var c = consumer{}
go p.produce()
go c.consumer()
time.Sleep(10000)
}