生产者-消费者模型的两种实现方式
https://www.cnblogs.com/caolicangzhu/p/7086176.html
本文主要来总结生产者-消费者模型的代码实现,至于其原理,请大家自行百度.
一、基于链表的生产-消费模型(条件变量)
我们以链表为例,生产者进行头部插入,消费者进行头部删除,因此,先将链表相关操作封装为LinkList.h,具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
//文件说明:LinkList.h
//作者:高小调
//创建时间:2017年06月27日 星期二 14时57分27秒
//开发环境:Kali Linux/g++ v6.3.0
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>
//链表节点
typedef struct LinkListNode{
int val;
struct inkListNode *next;
}Node,*pNode,**ppNode;
//初始化链表
void InitLinkList(ppNode head){
assert (head);
*head = NULL;
}
//判断链表是否为空
int IsEmpty(pNode head){
return head==NULL;
}
//申请新节点
pNode BuyNewNode( int val){
pNode ret = (pNode) malloc ( sizeof (Node));
ret->val = val;
ret->next = NULL;
return ret;
}
//头插
void PushFront(ppNode head, int val){
assert (head);
if (*head==NULL){
*head = BuyNewNode(val);
return ;
}
pNode newNode = BuyNewNode(val);
newNode->next = *head;
*head = newNode;
}
//头删
void PopFront(ppNode head, int *val){
assert (head);
if ((*head) == NULL){
return ;
}
if ((*head)->next == NULL){
*val = (*head)->val;
free (*head);
*head = NULL;
return ;
}
pNode del = *head;
*head = del->next;
*val = del->val;
free (del);
}
//销毁链表
void Destory(ppNode head){
assert (head);
pNode cur = *head;
pNode del = NULL;
while (cur!=NULL){
del = cur;
cur = cur->next;
free (del);
}
*head = NULL;
}
//打印链表
void PrintLinkList(pNode head){
pNode cur = head;
while (cur!=NULL){
printf ( "%d " ,cur->val);
cur = cur->next;
}
printf ( "\n" );
}
|
然后进入我们线程的生产消费模型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
//文件说明:test.c
//作者:高小调
//创建时间:2017年06月27日 星期二 14时56分13秒
//开发环境:Kali Linux/g++ v6.3.0
#include<stdio.h>
#include<pthread.h>
#include"LinkList.h"
//互斥锁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//测试链表
void TestLinkList(){
pNode head;
InitLinkList(&head);
int tmp;
for ( int i=0; i<10; ++i){
PushFront(&head,i);
PrintLinkList(head);
}
for ( int i=0; i<10; ++i){
PopFront(&head,&tmp);
PrintLinkList(head);
}
}
pNode head;
//生产者:每次向头节点插入数据
void *Productor( void *arg){
int val = 0;
while (1){
//互斥锁加锁:确保生产时不会消费,消费时不会生产
pthread_mutex_lock(&lock);
val = rand ()%100;
PushFront(&head,val);
printf ( "Productor push %d\n" ,val);
//互斥锁解锁
pthread_mutex_unlock(&lock);
//条件变量,生产完成之后向消费者发出信号消费
pthread_cond_signal(&cond);
sleep(1);
}
}
//消费者:每次将头节点数据取出
void *Consumer( void *arg){
int val = 0;
while (1){
//互斥锁
pthread_mutex_lock(&lock);
while (head==NULL){
//链表中没数据,阻塞等待生产者发消费信号
printf ( "wait for data\n" );
pthread_cond_wait(&cond,&lock);
}
PopFront(&head,&val);
printf ( "Consumer pop %d\n" ,val);
pthread_mutex_unlock(&lock);
sleep(1);
}
}
int main(){
InitLinkList(&head);
pthread_t cid1,cid2;
pthread_create(&cid1,NULL,Productor,NULL);
pthread_create(&cid2,NULL,Consumer,NULL);
pthread_join(&cid1,NULL);
pthread_join(&cid2,NULL);
return 0;
}
|
二、基于环形队列的生产-消费模型(信号量)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
//文件说明:test2.c
//作者:高小调
//创建时间:2017年06月27日 星期二 16时29分30秒
//开发环境:Kali Linux/g++ v6.3.0
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<stdlib.h>
#define SIZE 1024
//环形队列
int arr[SIZE] = {0};
sem_t sem_pro; //描述环形队列中的空位置
sem_t sem_con; //描述唤醒队列中的数据
//生产者,只要环形队列有空位,便不断生产
void *productor( void *arg){
int data = 0;
int proIndex = 0;
while (1){
//有空位便生产,没空位便阻塞等消费者消费
sem_wait(&sem_pro);
data = rand ()%1234;
arr[proIndex] = data;
printf ( "product done %d\n" ,data);
proIndex = (proIndex+1)%SIZE;
//供消费者消费的数据加1
sem_post(&sem_con);
}
}
//消费者,只要环形队列中有数据,就不断消费
void *consumer( void *arg){
int data = 0;
int conIndex = 0;
while (1){
//环形队列中存在数据则消费,不存在数据则阻塞,直到有数据为止
sem_wait(&sem_con);
data = arr[conIndex];
printf ( "consume done %d\n" ,data);
conIndex = (conIndex+1)%SIZE;
//最后,消费了一个数据,空位加1
sem_post(&sem_pro);
}
}
int main(){
pthread_t pro,con;
sem_init(&sem_pro,0,SIZE-1); //一开始有很多空位置
sem_init(&sem_con,0,0); //但并没有数据
pthread_create(&pro,NULL,productor,NULL);
pthread_create(&con,NULL,consumer,NULL);
pthread_join(pro,NULL);
pthread_join(con,NULL);
sem_destroy(&sem_pro);
sem_destroy(&sem_con);
return 0;
}
|
生产者-消费者模型的两种实现方式相关推荐
- 操作系统:生产者消费者模型的两种实现(C++)
文章目录 生产者消费者模型 什么是生产者消费者模型 生产者消费者模型的321原则 生产者消费者模型的优点 生产者消费者模型的实现方法 基于循环队列,信号量实现 基于阻塞队列,互斥锁.条件变量实现 生产 ...
- 生产者消费者模型的三种实现方式
某个线程或模块的代码负责生产数据(工厂),而生产出来的数据却不得不交给另一模块(消费者)来对其进行处理,在这之间使用了队列.栈等类似超市的东西来存储数据(超市),这就抽象除了我们的生产者/消费者模型. ...
- 【1】生产者-消费者模型的三种实现方式
(手写生产者消费者模型,写BlockingQueue较简便 ) 1.背景 ...
- 生产者-消费者模式的三种实现方式
2.生产者-消费者模式的三种实现方式 1.背景 生产者生产数据到缓 ...
- java生产者消费者流程图_Java 生产者消费者模型的三种实现过程
生产者一边在生产,消费者一边消耗.当库存满的时候生产者暂停生产,直到有空位:当库存空的时候消费者暂停消费,直到有产品. 关键点: 生产者和消费者都是在不断生产和消费的,是同时并发的,不应该等满了再消费 ...
- Java生产者 消费者模型的一种实现
本文主要介绍java中生产者/消费者模式的实现,对java线程锁机制的一次深入理解. 生产者/消费者模型 生产者/消费者模型要保证,同一个资源在同一时间节点下只能被最多一个线程访问,这个在java中用 ...
- 生产者消费者模式的三种实现方式
原作者:老铁123 出处:https://blog.csdn.net/qewgd/article/details/85926275 本文归作者[老铁123]和博客园共有,欢迎转载,但未经作者同意必须保 ...
- 操作系统 —— 生产者消费者模型
文章目录 1. 生产者消费者模型的理解 1.1 串行的概念 1.2 并行的概念 1.3 简单总结: 2. 基于阻塞队列(block queue)实现此模型 2.1 阻塞队列的实现 2.2 使用阻塞队列 ...
- java 生产者消费者_Java多线程:线程间通信—生产者消费者模型
一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是, 多个线程之间如何协作呢 ? 我们看一个 ...
最新文章
- 将计算机设置成交换机主机名,CISCO2950交换机的配置(设置密码、IP地址、主机名)...
- [css] 分析比较opacity: 0、visibility: hidden、display: none三者的优劣和适用场景
- mysql 5.7 hint_新特性解读 | MySQL 8.0 新增 HINT 模式
- 记录一种多个按钮中每次只能选中一个的实现方式
- CentOS操作系统keepalived安装步骤
- redis同步到磁盘
- Servlet(10)—请求转发和请求重定向
- php srs api,文档中心
- 单片机——电子密码锁设计报告
- jspstudy启动mysql失败_mysql启动失败的一个解决方法
- 计算机硬盘改回基本磁盘,将动态磁盘更改回基本磁盘
- java 方差_方差(Variance)
- 鼠标移上去变小手样式
- CoppeliaSim(原Vrep)中实现多关节机械臂的正运动学仿真【CoppeliaSim与matlab共享内存通信实现】
- 交替性注意力_如何培养共同注意力(Joint Attention)——社会性发展基石
- 博图在线升级 gsd_美生在线消费全返张鹏海外大举收割国内韭菜。
- Ubuntu20.04使用摸索(二)——蓝牙耳机连接
- docusign文档打不开_关于salesforce:创建Docusign文档并从其他系统发送电子邮件
- vs2015c语言函数,c++中strcpy函数在VS2015无法使用的问题
- ABAP~ 内表操作
热门文章
- jquery-基础事件[下]
- thinkphp 删除该表的最后一行
- 辅助的写与数据库交互的XML文件的类
- XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置
- [我研究]Behavior Based Software Theft Detection - Hawk
- 给ULWOW 写的广告效果(缓动切换)
- 晚上答辩的理论知识准备
- android horizontalscrollview 动画,Android HorizontalScrollView左右滑动效果
- linux运维笔试题目,linux运维相关的笔试题目_笔试题目
- linux 命令分号,linux命令之间的分号,, ||