生产者消费者问题

用信号量机制解决生产者消费者问题

南笙酒味 提交于 2020-12-14 09:15:33
使用POSIX标准中的Pthreads API来创建多个生产者、消费者线程 定义线程:pthread_t tid 创建线程:pthread_create(&tid,&attr,runner,argv[1]); join线程:pthread_join(tid,NULL); 使用PthreadsAPI的信号量机制互斥与同步 定义信号量:sem_t sem 初始化信号量:sem_init(&sem, 0, n); P操作:sem_wait(&sem); V操作:sem_post(&sem); #include <stdio.h> #include <pthread.h> #include <semaphore.h> #define BUFF_SIZE 5 // 定义缓冲区buffer大小为5 int buffer[BUFF_SIZE]; // 用循环队列模拟缓冲区 int in = 0; // 产品进缓冲区时的缓冲区下标 int out = 0; // 产品出缓冲区时的缓冲区下标 int productID = 0; // 产品号 int consumeID = 0; // 将被消耗的产品号 sem_t s; // 定义互斥信号量, 互斥锁s sem_t n; // 定义同步信号量n, buffer中已放入的产品个数 sem_t e; // 定义同步信号量e, buffer中空单元个数

java中线程队列BlockingQueue的用法

試著忘記壹切 提交于 2020-04-07 11:09:48
在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。 [ @more @] 认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示: 从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出; 常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种)   先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。   后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。 多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程,利用队列的方式来传递数据,就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内

python进程——生产者消费者

烂漫一生 提交于 2020-04-03 18:39:12
生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。 同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。 什么是生产者和消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列, 消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。 这个阻塞队列就是用来给生产者和消费者解耦的 生产者消费者模型实现 from multiprocessing import Process,Queue import time def producer(q,name,food): """ 生产者 :param q: 队列 :param name: :param food: :return: """ for i in range(3): res = '%s,%s' %(food,i) time.sleep(1) # 生产food得有个过程,就先让睡一会 print('生产者[%s]

Java 多线程总结

限于喜欢 提交于 2020-03-28 06:29:36
昨天熬了个通宵,看了一晚上的视频,把java 的多线程相关技术重新复习了一遍,下面对学习过程中遇到的知识点进行下总结。 首先我们先来了解一下进程、线程、并发执行的概念:   进程是指: 一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。 线程是指: 进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。 一般来说, 当运行一个应用程序的时候,就启动了一个进程,当然有些会启动多个进程。启动进程的时候,操作系统会为进程分配资源,其中最主要的资源是内存空间,因为程序是在内存中运行的。 在进程中,有些程序流程块是可以乱序执行的,并且这个代码块可以同时被多次执行。实际上,这样的代码块就是线程体。线程是进程中乱序执行的代码流程。当多个线程同时运行的时候,这样的执行模式成为并发执行。 线程的状态 1、线程共有下面4种状态: 新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行。 就绪状态(Runnable): 线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。 运行状态(Running):

BlockingQueue(阻塞队列)详解

*爱你&永不变心* 提交于 2020-03-24 10:02:50
注意:该随笔内容完全引自http://wsmajunfeng.iteye.com/blog/1629354,写的很好,非常感谢,复制过来算是个积累,怕以后找不到。 一. 前言   在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。 二. 认识BlockingQueue   阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示:   从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出;   常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种)     先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。     后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。   多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享

python并发编程之多进程理论部分

本小妞迷上赌 提交于 2020-03-23 05:41:13
内容概要 操作系统介绍 进程 线程 协程 二. 进程 python并发编程之多进程理论部分 在python程序中的进程操作   运行中的程序就是一个进程。所有的进程都是通过它的父进程来创建的。因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建子进程。多个进程可以实现并发效果,也就是说,当我们的程序中存在多个进程的时候,在某些时候,就会让程序的执行速度变快。创建进程这个功能需要借助python中强大的模块。 multiprocess模块   multiprocess不是一个模块而是python中一个操作、管理进程的包。 这个包中几乎包含了和进程有关的所有子模块。大致分为四个部分:创建进程部分,进程同步部分,进程池部分,进程之间数据共享。 multiprocess.process模块 process模块介绍   process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建。 class Process(object): def __init__(self, group=None, target=None, name=None, args=(), kwargs={}): self.name = '' self.daemon = False self.authkey = None self.exitcode = None self.ident = 0

[golang]单向channel的应用“生产消费者模型”

喜你入骨 提交于 2020-03-21 04:28:19
单向channel应用“生产消费者模型” 单向channel最典型的应用是“生产者消费者模型” 所谓“生产者消费者模型”: 某个模块(函数等)负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、协程、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。 单单抽象出生产者和消费者,还够不上是生产者/消费者模型。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。生产者把数据放入缓冲区,而消费者从缓冲区取出数据。大概的结构如下图: 举一个寄信的例子来辅助理解一下,假设你要寄一封平信,大致过程如下: 把信写好——相当于生产者制造数据 把信放入邮筒——相当于生产者把数据放入缓冲区 邮递员把信从邮筒取出——相当于消费者把数据取出缓冲区 邮递员把信拿去邮局做相应的处理——相当于消费者处理数据 那么,这个缓冲区有什么用呢?为什么不让生产者直接调用消费者的某个函数,直接把数据传递过去,而画蛇添足般的设置一个缓冲区呢? 缓冲区的好处大概如下: 1:解耦 假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来如果消费者的代码发生变化,可能会直接影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合度也就相应降低了。 接着上述的例子,如果不使用邮筒

JAVA并发编程-线程间协作(Object监视器方法与Condition)

二次信任 提交于 2020-03-17 11:21:32
某厂面试归来,发现自己落伍了!>>> 原文地址: http://blog.csdn.net/zhshulin/article/details/50762465 下面只是简单的介绍一下,具体代码可以看我分享的代码,注释都有 说到线程间协作,不得不提到经典的 生产者与消费者模型 :有一个商品队列,生产者想队列中添加商品,消费者取出队列中的商品;显然,如果队列为空,消费者应该等待生产者产生商品才能消费;如果队列满了,生产者需要等待消费者消费之后才能生产商品。队列就是这个模型中的临界资源,当队列为空时,而消费者获得了该对象的锁,如果不释放,那么生产者无法获得对象锁,而消费者无法消费对象,就进入了死锁状态;反之队列满时,生产者不释放对象锁也会造成死锁。这是我们不希望看到的,所以就有了线程间协作来解决这个问题。 其实说到生产者与消费者模型,我们不能简单的知道怎么实现,而是需要知这种模型的使用场景:主要是为了复用和解耦, 常见的消息框架(非常经典的一种生产者消费者模型的使用场景) ActiveMQ 。发送端和接收端用Topic进行关联。 JAVA语言中,如何实现线程间协作呢?比较常见的方法就是利用Object.wait(),Object.notify()和Condition。 先看看这几个方法究竟有什么作用?为什么利用它们就可以实现线程间协作了呢? 首先分析一下wait()/notify()

生产者消费者模型、读者写者模型

耗尽温柔 提交于 2020-03-17 08:22:04
生产者与消费者模型 什么是生产者消费者模型 某个模块负责产生数据,这些数据由另一个模块来负责处理,产生数据的模块,形象地称为生产者,而处理数据的模块,就称为消费者,该模式还需有一个缓冲区处于生产者和消费者之间,作为一个中介,生产者把数据放入缓冲区,而消费者从缓冲区取出数据。在多线程编程中阻塞队列(Blocking Queue)是一种常用于实现生产者和消费者模型的数据结构。其与普通的队列区 别在于:当队列为空时,从队列获取元素的操作将会被阻塞,直到队列中被放入了元素;当队列满时,往队列里存 放元素的操作也会被阻塞,直到有元素被从队列中取出 为什么要使用生产者消费者模型 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯, 而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生 产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个 阻塞队列就是用来给生产者和消费者解耦的。 生产者与消费者之间的关系 1.三种关系:生产者与生产者(互斥)、消费者与消费者(互斥)、生产者与消费者(互斥、同步) 2.两种角色:生产者 、消费者 3.一种场所:为生产者与消费者提供数据单元的缓冲区 为了方便记忆:321原则 生产者与消费者模型的优点 1、解耦合

如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

二次信任 提交于 2020-03-16 02:26:09
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。 在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。。举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。 我们可以利用wait()来让一个线程在某些条件下暂停运行。例如,在生产者消费者模型中,生产者线程在缓冲区为满的时候,消费者在缓冲区为空的时候,都应该暂停运行。如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待中的线程重新开始运行。不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待中的线程。换言之,如果只有一个线程在等待一个信号灯,notify和notifyAll都会通知到这个线程。但如果多个线程在等待这个信号灯,那么notify只会通知到其中一个,而其它线程并不会收到任何通知,而notifyAll会唤醒所有等待中的线程。 在这篇文章中你将会学到如何使用