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;
}

生产者-消费者模型的两种实现方式相关推荐

  1. 操作系统:生产者消费者模型的两种实现(C++)

    文章目录 生产者消费者模型 什么是生产者消费者模型 生产者消费者模型的321原则 生产者消费者模型的优点 生产者消费者模型的实现方法 基于循环队列,信号量实现 基于阻塞队列,互斥锁.条件变量实现 生产 ...

  2. 生产者消费者模型的三种实现方式

    某个线程或模块的代码负责生产数据(工厂),而生产出来的数据却不得不交给另一模块(消费者)来对其进行处理,在这之间使用了队列.栈等类似超市的东西来存储数据(超市),这就抽象除了我们的生产者/消费者模型. ...

  3. 【1】生产者-消费者模型的三种实现方式

    (手写生产者消费者模型,写BlockingQueue较简便 ) 1.背景                                                                 ...

  4. 生产者-消费者模式的三种实现方式

    2.生产者-消费者模式的三种实现方式 1.背景                                                                    生产者生产数据到缓 ...

  5. java生产者消费者流程图_Java 生产者消费者模型的三种实现过程

    生产者一边在生产,消费者一边消耗.当库存满的时候生产者暂停生产,直到有空位:当库存空的时候消费者暂停消费,直到有产品. 关键点: 生产者和消费者都是在不断生产和消费的,是同时并发的,不应该等满了再消费 ...

  6. Java生产者 消费者模型的一种实现

    本文主要介绍java中生产者/消费者模式的实现,对java线程锁机制的一次深入理解. 生产者/消费者模型 生产者/消费者模型要保证,同一个资源在同一时间节点下只能被最多一个线程访问,这个在java中用 ...

  7. 生产者消费者模式的三种实现方式

    原作者:老铁123 出处:https://blog.csdn.net/qewgd/article/details/85926275 本文归作者[老铁123]和博客园共有,欢迎转载,但未经作者同意必须保 ...

  8. 操作系统 —— 生产者消费者模型

    文章目录 1. 生产者消费者模型的理解 1.1 串行的概念 1.2 并行的概念 1.3 简单总结: 2. 基于阻塞队列(block queue)实现此模型 2.1 阻塞队列的实现 2.2 使用阻塞队列 ...

  9. java 生产者消费者_Java多线程:线程间通信—生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是, 多个线程之间如何协作呢 ? 我们看一个 ...

最新文章

  1. 将计算机设置成交换机主机名,CISCO2950交换机的配置(设置密码、IP地址、主机名)...
  2. [css] 分析比较opacity: 0、visibility: hidden、display: none三者的优劣和适用场景
  3. mysql 5.7 hint_新特性解读 | MySQL 8.0 新增 HINT 模式
  4. 记录一种多个按钮中每次只能选中一个的实现方式
  5. CentOS操作系统keepalived安装步骤
  6. redis同步到磁盘
  7. Servlet(10)—请求转发和请求重定向
  8. php srs api,文档中心
  9. 单片机——电子密码锁设计报告
  10. jspstudy启动mysql失败_mysql启动失败的一个解决方法
  11. 计算机硬盘改回基本磁盘,将动态磁盘更改回基本磁盘
  12. java 方差_方差(Variance)
  13. 鼠标移上去变小手样式
  14. CoppeliaSim(原Vrep)中实现多关节机械臂的正运动学仿真【CoppeliaSim与matlab共享内存通信实现】
  15. 交替性注意力_如何培养共同注意力(Joint Attention)——社会性发展基石
  16. 博图在线升级 gsd_美生在线消费全返张鹏海外大举收割国内韭菜。
  17. Ubuntu20.04使用摸索(二)——蓝牙耳机连接
  18. docusign文档打不开_关于salesforce:创建Docusign文档并从其他系统发送电子邮件
  19. vs2015c语言函数,c++中strcpy函数在VS2015无法使用的问题
  20. ABAP~ 内表操作

热门文章

  1. jquery-基础事件[下]
  2. thinkphp 删除该表的最后一行
  3. 辅助的写与数据库交互的XML文件的类
  4. XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置
  5. [我研究]Behavior Based Software Theft Detection - Hawk
  6. 给ULWOW 写的广告效果(缓动切换)
  7. 晚上答辩的理论知识准备
  8. android horizontalscrollview 动画,Android HorizontalScrollView左右滑动效果
  9. linux运维笔试题目,linux运维相关的笔试题目_笔试题目
  10. linux 命令分号,linux命令之间的分号,, ||