golang并发编程之生产者消费者(代码片段)

hatlonely hatlonely     2022-10-24     414

关键词:

golang 最吸引人的地方可能就是并发了,无论代码的编写上,还是性能上面,golang 都有绝对的优势

学习一个语言的并发特性,我喜欢实现一个生产者消费者模型,这个模型非常经典,适用于很多的并发场景,下面我通过这个模型,来简单介绍一下 golang 的并发编程

go 并发语法

协程 go

协程是 golang 并发的最小单元,类似于其他语言的线程,只不过线程的实现借助了操作系统的实现,每次线程的调度都是一次系统调用,需要从用户态切换到内核态,这是一项非常耗时的操作,因此一般的程序里面线程太多会导致大量的性能耗费在线程切换上。而在 golang 内部实现了这种调度,协程在这种调度下面的切换非常的轻量级,成百上千的协程跑在一个 golang 程序里面是很正常的事情

golang 为并发而生,启动一个协程的语法非常简单,使用 go 关键字即可

go func () 
    // do something

同步信号 sync.WaitGroup

多个协程之间可以通过 sync.WaitGroup 同步,这个类似于 Linux 里面的信号量

var wg sync.WaitGroup  // 申明一个信号量
wg.Add(1)   // 信号量加一
wg.Done()   // 信号量减一
wg.Wait()   // 信号量为正时阻塞,直到信号量为0时被唤醒

通道 chan

通道可以理解为一个消息队列,生产者往队列里面放,消费者从队列里面取。通道可以使用 close 关闭

ic := make(chan int, 10)  // 申明一个通道
ic <- 10        // 往通道里面放
i := <- ic      // 从通道里面取

close(ic)       // 关闭通道

生产者消费者实现

定义产品类

这个产品类根据具体的业务需求定义

type Product struct 
    name  int
    value int

生产者

如果 stop 标志不为 false,不断地往通道里面放 product,完成之后信号量完成

func producer(wg *sync.WaitGroup, products chan<- Product, name int, stop *bool) 
    for !*stop 
        product := Productname: name, value: rand.Int()
        products <- product
        fmt.Printf("producer %v produce a product: %#v\n", name, product)
        time.Sleep(time.Duration(200+rand.Intn(1000)) * time.Millisecond)
    
    wg.Done()

消费者

不断地从通道里面取 product,然后作对应的处理,直到通道被关闭,并且 products 里面为空, for 循环才会终止,而这正是我们期望的

func consumer(wg *sync.WaitGroup, products <-chan Product, name int) 
    for product := range products 
        fmt.Printf("consumer %v consume a product: %#v\n", name, product)
        time.Sleep(time.Duration(200+rand.Intn(1000)) * time.Millisecond)
    
    wg.Done()

主线程

var wgp sync.WaitGroup
var wgc sync.WaitGroup
stop := false
products := make(chan Product, 10)

// 创建 5 个生产者和 5 个消费者
for i := 0; i < 5; i++ 
    go producer(&wgp, products, i, &stop)
    go consumer(&wgc, products, i)
    wgp.Add(1)
    wgc.Add(1)


time.Sleep(time.Duration(1) * time.Second)
stop = true     // 设置生产者终止信号
wgp.Wait()      // 等待生产者退出
close(products) // 关闭通道
wgc.Wait()      // 等待消费者退出

转载请注明出处
本文链接:http://hatlonely.github.io/2018/03/11/golang-%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85/

java并发编程实战之基于生产者消费者模式的日志服务读书笔记(代码片段)

...;我们会经常跟日志系统打交道,日志系统算是典型的生产者消费者模型的系统。(多个不同的)生产者线程负责生产日志消息,这些系统扮演者生产者的角色,日志系统负责将消息队列里的日志上传到服务器&... 查看详情

java并发编程实战之基于生产者消费者模式的日志服务读书笔记(代码片段)

...;我们会经常跟日志系统打交道,日志系统算是典型的生产者消费者模型的系统。(多个不同的)生产者线程负责生产日志消息,这些系统扮演者生产者的角色,日志系统负责将消息队列里的日志上传到服务器&... 查看详情

第36天并发编程之进程篇(代码片段)

...方法  5.守护进程  6.互斥锁  7.IPC通信机制  8.生产者消费者模型一.基础概念1.什么叫做程序,什么叫做进程?    程序就是程序员写的一堆代码文件。  进程指的是程序正在执行的一个过程,是一个抽象的概念... 查看详情

42_并发编程-jionablequeue(代码片段)

一、生产者消费者模型    在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,... 查看详情

并发编程基础之生产者消费者模式

一:概念生产者消费者模式是java并发编程中很经典的并发情况,首先有一个大的容器,生产者put元素到容器中,消费者take元素出来,如果元素的数量超过容器的容量时,生产者不能再往容器中put元素,处于阻塞状态,如果元素... 查看详情

19.并发容器之blockingqueue(代码片段)

...Queue(关于ConcurrentLinkedQueue可以看这篇文章)。最常用的"生产者-消费者"问题中,队列通常被视作线程间操作的数据容器,这样,可以对各个模块的业务功能进行解耦,生产者将“生产”出来的数据放置在数据容器中,而消费者... 查看详情

java——多线程高并发系列之生产者-消费者模式(代码片段)

...2测试结果3写在前面在Java中,负责生产数据的模块是生产者,负责使用数据的模块是消费者。生产者消费者解决数据的平衡问题,即先有数据然后才能使用,没有数据时,消费者需要等待。下面的案例中& 查看详情

day855.生产者-消费者模式-java并发编程实战(代码片段)

生产者-消费者模式Hi,我是阿昌,今天学习记录的是关于生产者-消费者模式的内容。WorkerThread模式类比的是工厂里车间工人的工作模式。但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域&#x... 查看详情

day855.生产者-消费者模式-java并发编程实战(代码片段)

生产者-消费者模式Hi,我是阿昌,今天学习记录的是关于生产者-消费者模式的内容。WorkerThread模式类比的是工厂里车间工人的工作模式。但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域&#x... 查看详情

5并发编程--队列&生产者消费者模型(代码片段)

1、队列的介绍进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的创建队列的类(底层就是以管道和锁定的方式实现):Queue([maxsize]):创建共享的进程... 查看详情

并发编程之多进程3(生产者与消费者模型)回调函数

一、生产者消费模型补充  总结:    ---生产者消费者模型程序中两种角色:①负责生产数据(生产者);②负责处理数据(消费者)    ---生产者消费者模型的作用:平衡生产者与消费者之间的速度差。    ---... 查看详情

并发编程的那些事儿(代码片段)

1、生产者和消费者模型  作用:用于解耦。  原理:生产者将生产的数据放到缓存区,消费者从缓存区直接取。借助队列来实现该模型(队列就是缓存区)  队列是安全的,自带锁机制。  q=Queue(num)  num为队列的最... 查看详情

golang并发编程之channel(代码片段)

一、概念channel是golang语言级别提供的协程(goroutine)之间的通信方式。goroutine运行在相同的地址空间,因此访问共享内存必须做好同步。那么goroutine之间如何进行数据的通信呢,Go提供了一个很好的通信机制channel。channel可以与Unixs... 查看详情

高并发编程学习——线程通信详解(代码片段)

...m/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-ji-chu/一、经典的生产者消费者案例上一篇文章我们提到一个应用可以创建多个线程去执行不同的任务,如果这些任务之间有着某种关系,那么线程之间必须能够通信来协调完成工作。生产... 查看详情

python复习—并发编程实战——多线程和多进程的生产者消费者模型线程进程再总结(代码片段)

任务生产者负责生产数据(随机生成一个数字),消费者负责处理数据(判断生产出来的数据是不是质数)。现在假设有一个生产者和多个消费者。1.多线程(Thread)的生产者消费者模型importrandomimportti... 查看详情

go模式-生产者消费者(代码片段)

常见的生产者消费者,就是多个生产者并发生产数据,多个消费者并发消费数据。在golang中很简单,生产者生产全部输入到channel中,消费者消费全部从channel中读取,天然具有并发安全性。1.group消费channel有如... 查看详情

go模式-生产者消费者(代码片段)

常见的生产者消费者,就是多个生产者并发生产数据,多个消费者并发消费数据。在golang中很简单,生产者生产全部输入到channel中,消费者消费全部从channel中读取,天然具有并发安全性。1.group消费channel有如... 查看详情

go模式-生产者消费者(代码片段)

常见的生产者消费者,就是多个生产者并发生产数据,多个消费者并发消费数据。在golang中很简单,生产者生产全部输入到channel中,消费者消费全部从channel中读取,天然具有并发安全性。1.group消费channel有如... 查看详情