分享
  1. 首页
  2. 文章

几个常见的并发模型——生产者消费者模型【Golang 入门系列十七】

mb5fe94b3e552d9 · · 792 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前面已经讲过很多Golang系列知识,包括并发,锁等内容,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863.html,

接下来讲几个golang常见的并发模型,今天先说说生产者消费者模型。

生产者消费者模型

图片

生产者:发送数据端

消费者:接收数据端

缓冲区:
1. 解耦(降低生产者和消费者之间耦合度)

2. 并发(生产者消费者数量不对等时,能保持正常通信)

3. 缓存(生产者和消费者 数据处理速度不一致时,暂存数据)

如何实现?

生产者消费者模型是非常常见的并发模型,而且golang提供了chan类型,可以很方便的实现。

根据 golang的官方文档,使用chan就可以实现生产者和消费者之间的数据和状态同步。

  • 通过chan在生产者和消费者之间传递数据(ch)和同步状态(done);

  • chan作为参数传递时是引用传递,不需要使用指针;

  • chan是协程安全的,多个goroutine之间不需要锁;

  • chan的close事件可以被recv获取,close事件一定在正常数据读完之后,机制类似于read到EOF;

示例代码:
package main
import "fmt"
func Producer(ch chan int) { for i := 1; i <= 10; i++ { ch <- i } close(ch)}
func Consumer(id int, ch chan int, done chan bool) { for { value, ok := <-ch if ok { fmt.Printf("id: %d, recv: %d\n", id, value) } else { fmt.Printf("id: %d, closed\n", id) break } } done <- true}
func main() { ch := make(chan int, 3)
coNum := 2 done := make(chan bool, coNum) for i := 1; i <= coNum; i++ { go Consumer(i, ch, done) }
go Producer(ch)
for i := 1; i <= coNum; i++ { <-done }}
运行结果:id: 2, recv: 1id: 1, recv: 2id: 1, recv: 4id: 1, recv: 5id: 1, recv: 6id: 2, recv: 3id: 2, recv: 8id: 2, recv: 9id: 2, recv: 10id: 2, closedid: 1, recv: 7id: 1, closed

简单说明:

1、首先创建一个双向的channel,

2.、然后开启一个新的goroutine,把双向通道作为参数传递到producer方法中,同时转成只写通道。子协程开始执行循环,向只写通道中添加数据,这就是生产者。

3、主协程,直接调用consumer方法,该方法将双向通道转成只读通道,通过循环每次从通道中读取数据,这就是消费者。


注意:channel作为参数传递,是引用传递。

缓冲区的好处

1:解耦
假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来如果消费者的代码发生变化,可能会直接影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合度也就相应降低了。

2:处理并发
生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只好一直等在那边。万一消费者处理数据很慢,生产者只能无端浪费时间。
使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。
其实最当初这个生产者消费者模式,主要就是用来处理并发问题的。

3:缓存
如果生产者制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。

最后

以上,就把golang生产者消费者模型简单介绍完了,希望能对大家有所帮助。



有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
792 次点击
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏