go使用条件变量实现生产者消费者模型
2018-09-07 20:41
1201 查看
概述
前面已经学习过使用channel完成简单的生产者消费者模型了,但那种模型存在一定的弊端,生产者消费者数量增加时,数据容易紊乱或被堵塞,而使用条件变量实现的生产者消费者模型可以有效解决这一点。
所需知识点
条件变量:条件变量的作用并不保证在同一时刻仅有一个协程(线程)访问某个共享的数据资源,而是在对应的共享数据的状态发生变化时,通知阻塞在某个条件上的协程(线程)。条件变量不是锁,在并发中不能达到同步的目的,因此条件变量总是配合锁一起使用。
上代码之前我们首先需要知道其中重要的一个难点,即条件变量对应的三个常用方法Wait(),Signal(),Broadcast().
1) func (c *Cond) Wait()
该函数的作用可归纳为如下三点:
a) 阻塞等待条件变量满足
b) 释放已掌握的互斥锁相当于cond.L.Unlock()。注意:两步为一个原子操作。
所谓的原子操作的意思是以上两步操作不可分离,一旦启动即两步同时执行。
c) 当被唤醒,Wait()函数返回时,解除阻塞并重新获取互斥锁。相当于cond.L.Lock()
2) func (c *Cond) Signal()
单发通知,给一个正等待(阻塞)在该条件变量上的goroutine(线程)发送通知。
3) func (c *Cond) Broadcast()
广播通知,给正在等待(阻塞)在该条件变量上的所有goroutine(线程)发送通知。
//一般情况下不使用broadcast,会引起惊群!所以我们下面使用Signal函数
理解以上知识点后,再来理解条件变量的使用就比较容易了,上代码:
代码
package main import ( "sync" "math/rand" "time" "fmt" ) var cond sync.Cond//创建全局条件变量 func producter(ch chan<- int) { for { cond.L.Lock() //go进程进来后,不多比比,先上锁 for len(ch)==3 { /*注意这里是for而不是if,判断缓冲 区里是不是有太多数据,如果满了,则持续阻塞,直至对面发来signal信号*/ cond.Wait() } num:=rand.Intn(1000) ch<-num fmt.Println("已生产",num) cond.L.Unlock()//生产完毕后解锁并给对面发信号 cond.Signal() time.Sleep(time.Millisecond*300) } } func consumer(ch <-chan int) { for { cond.L.Lock()//以下都是跟上面一样的 for len(ch)==0 { cond.Wait() } num:=<-ch fmt.Println("已消费:",num) cond.L.Unlock() cond.Signal() time.Sleep(time.Millisecond*300) } } func main() { //给全局变量加上一个锁的功能,相当于给他加个装备 cond.L=new(sync.Mutex) var ch chan int=make(chan int,3) var quit chan string rand.Seed(time.Now().UnixNano()) for i:=0;i<5 ;i++ { go producter(ch) } for i:=0;i<3 ;i++ { go consumer(ch) } <-quit//这个管道是故意阻塞在这里,防止主进程结束 }
有问题的小伙伴可以给我留言哦
阅读更多相关文章推荐
- windows 使用关键段和条件变量实现的生产者和消费者线程同步
- POSIX 使用互斥量和条件变量实现生产者/消费者问题
- Java多线程使用wait和notify实现生产者消费者模型
- Java多线程之~~~~使用wait和notify实现生产者消费者模型
- 互斥量和条件变量实现生产者消费者模型
- 使用swoole实现生产者消费者模型(2)
- 使用Boost.Tread库实现生产者消费者模型
- 使用blockingqueue实现的简单生产者消费者模型
- Java多线程之~~~~使用wait和notify实现生产者消费者模型
- 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题
- 简单的生产者和消费者模型——互斥锁和条件变量实现
- Java并发编程笔记 使用阻塞队列实现生产者-消费者模型
- 什么是阻塞队列?如何使用阻塞队列来实现生产者-消费者模型?
- Kafka使用go实现生产者和消费者
- 使用BlockingQueue实现生产者和消费者模型
- 使用semaphore实现生产者-消费者简单模型
- 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题
- 什么是阻塞队列? 如何使用阻塞队列来实现生产者-消费者模型?
- 使用wait和notifyAll实现生产者消费者模型
- 使用ReentrantLock和Condition实现生产者消费者模型