条件变量 实现2生产者2消费者模型

1个生产者在生产的时候,另个生产者不能生产(生产者之间互斥)

条件变量用于线程同步,线程挂起/被唤醒。
条件变量和互斥锁共同保证生产者之间互斥+生产者和消费者的同步。        

思路:


1 定义、初始化共享资源

a 缓冲区:存储物品。初始化为空。
b 计数器:缓冲区中物品数量。初始化为0。
c 互斥锁:缓冲区和计数器的互斥访问。初始化。
        4个线程共用一个锁
d 条件变量:生产者和消费者的同步。初始化。
        not_full 消费者消费后通知生产者(缓冲区不满);生产者在缓冲区满时等待不满;
        not_empty生产者生产后通知消费者(缓冲区不空);消费者在缓冲区空时等待不空。

2 创建两个生产者线程、两个消费者线程

生产者行为 

a 锁定互斥锁
b 检查条件:缓冲区是否已满。
        是则等待不满条件变量。 pthread_cond_wait(&not_full, &mutex)
c 条件允许,生产者生产物品并放入缓冲区。
d 计数器+1:增加物品。
e 条件变量通知消费者缓冲区非空。pthread_cond_signal(&not_empty)
f 释放互斥锁

消费者行为 

a 锁定互斥锁
b 检查条件:缓冲区是否为空。
        是则等待非空条件变量。pthread_cond_wait(&not_empty,&mutex)
c 条件允许,消费者从缓冲区中取一个物品。
d 计数器-1:减少物品。
e 条件变量通知生产者缓冲区未满。 pthread_cond_signal(&not_full)
f 释放互斥锁

清理资源

程序结束前,销毁互斥锁和条件变量。   

 代码

#define BUFFER_SIZE 10 // 定义缓冲区大小

int buffer[BUFFER_SIZE]; // 缓冲区数组
int in = 0; // 生产者放置物品的位置
int out = 0; // 消费者取物品的位置
int count = 0; // 缓冲区中的物品数量

pthread_mutex_t mutex; // 互斥锁,保护缓冲区
pthread_cond_t not_full; // 条件变量,缓冲区未满时通知生产者
pthread_cond_t not_empty; // 条件变量,缓冲区非空时通知消费者

// 生产者线程函数
void *producer(void *id) {
    int item;
    int *producer_id = (int *)id;

    while (1) {
        item = 'a' + rand() % 26; // 生产(小写字母)

        pthread_mutex_lock(&mutex);
        while (count == BUFFER_SIZE ) {// 缓冲区满,则等待
            pthread_cond_wait(&not_full, &mutex);// 等待未满条件变量
        }

        buffer[in] = item;//放入
        in = (in + 1) % BUFFER_SIZE;
        count++;
        printf("生产者%d号生产%c\n", *producer_id, item);
        
        pthread_cond_signal(&not_empty);// 通知消费者缓冲区非空
        pthread_mutex_unlock(&mutex);
        sleep(1); // 模拟生产时间
    }
    return NULL;
}
void *consumer(void *id) {
    int item;
    int *consumer_id = (int *)id;

    while (1) {
        pthread_mutex_lock(&mutex);
        while (count == 0) {//缓冲区空,则等待
            pthread_cond_wait(&not_empty, &mutex);// 等待非空条件变量
        }

        item = buffer[out];//消费
        out = (out + 1) % BUFFER_SIZE;
        count--;
        printf("消费者%d号消耗%c\n", *consumer_id, item);

        pthread_cond_signal(&not_full);// 通知生产者缓冲区未满
        pthread_mutex_unlock(&mutex);
        sleep(1); // 模拟消费时间
    }
    return NULL;
}

int main() {
    pthread_t producers[2], consumers[2];
    int producer_ids[2] = {1, 2};
    int consumer_ids[2] = {1, 2};
    //初始化
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&not_full, NULL);
    pthread_cond_init(&not_empty, NULL);

    // 创建生产者、消费者线程
    for (int i = 0; i < 2; i++) {
        pthread_create(&producers[i], NULL, producer, (void*)&producer_ids[i]);
        pthread_create(&consumers[i], NULL, consumer, (void*)&consumer_ids[i]);
    }
    // 等待线程结束
    for (int i = 0; i < 2; i++) {
        pthread_join(producers[i], NULL);
        pthread_join(consumers[i], NULL);
    }
    //销毁
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&not_full);
    pthread_cond_destroy(&not_empty);

    return 0;
}

运行结果 

生产者和消费者是无限循环的,所以程序需要外部干预来停止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/963013.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一个开源 GenBI AI 本地代理(确保本地数据安全),使数据驱动型团队能够与其数据进行互动,生成文本到 SQL、图表、电子表格、报告和 BI

一、GenBI AI 代理介绍&#xff08;文末提供下载&#xff09; github地址&#xff1a;https://github.com/Canner/WrenAI 本文信息图片均来源于github作者主页 在 Wren AI&#xff0c;我们的使命是通过生成式商业智能 &#xff08;GenBI&#xff09; 使组织能够无缝访问数据&…

使用C#开发一款通用数据库管理工具

由于经常使用各种数据库&#xff0c;笔者自己动手丰衣足食&#xff0c;使用C#开发了一款通用数据库管理工具&#xff0c;支持Mysql、Oracle、Sqlite、SQL Server等数据库的表、视图、存储过程、函数管理功能&#xff0c;并支持导入导出、数据字典生成、拖拽式跨机器跨库数据一键…

sqli-labs靶场通关

sqli-las通关 mysql数据库5.0以上版本有一个自带的数据库叫做information_schema,该数据库下面有两个表一个是tables和columns。tables这个表的table_name字段下面是所有数据库存在的表名。table_schema字段下是所有表名对应的数据库名。columns这个表的colum_name字段下是所有…

DNS缓存详解(DNS Cache Detailed Explanation)

DNS缓存详解 清空DNS缓存可以让网页访问更快捷。本文将从什么是DNS缓存、为什么清空DNS缓存、如何清空DNS缓存、清空DNS缓存存在的问题四个方面详细阐述DNS缓存清空的相关知识。 一、什么是DNS缓存 1、DNS缓存的定义&#xff1a; DNS缓存是域名系统服务在遇到DNS查询时自动…

【VM】VirtualBox安装CentOS8虚拟机

阅读本文前&#xff0c;请先根据 VirtualBox软件安装教程 安装VirtualBox虚拟机软件。 1. 下载centos8系统iso镜像 可以去两个地方下载&#xff0c;推荐跟随本文的操作用阿里云的镜像 centos官网&#xff1a;https://www.centos.org/download/阿里云镜像&#xff1a;http://…

2024第十五届蓝桥杯网安赛道省赛题目--rc4

rc4 一、查壳 无壳&#xff0c;32位 二、IDA分析 1.main 2.sub_401005 根据题目以及该函数的内容都可以让我们确定这是个rc4加密题。 所以

区块链项目孵化与包装设计:从概念到市场的全流程指南

区块链技术的快速发展催生了大量创新项目&#xff0c;但如何将一个区块链项目从概念孵化成市场认可的产品&#xff0c;是许多团队面临的挑战。本文将从孵化策略、包装设计和市场落地三个维度&#xff0c;为你解析区块链项目成功的关键步骤。 一、区块链项目孵化的核心要素 明确…

【机器学习】自定义数据集 使用scikit-learn中svm的包实现svm分类

一、支持向量机(support vector machines. &#xff0c;SVM)概念 1. SVM 绪论 支持向量机&#xff08;SVM&#xff09;的核心思想是找到一个最优的超平面&#xff0c;将不同类别的数据点分开。SVM 的关键特点包括&#xff1a; ① 分类与回归&#xff1a; SVM 可以用于分类&a…

电信传输基本理论/5G网络层次架构——超三万字详解:适用期末考试/考研/工作

电信传输的基本概念 信息、通信、电信、电信传输的定义 信息 信息指的是消息中的有效信息量 通信 通信指的是利用传输媒质将信息从一段传输到另一端 电信 电信的意思是利用电子技术来将信息从一段传输到另一端 电信传输 电信传输的概念就是将含有信息的电信号进行传输…

代码练习3

1 #include <stdio.h>void draw(int n) {for (int i n; i > 1; i--) {// 打印空格for (int j 0; j < n - i; j) {printf(" ");}// 打印星号for (int j 0; j < 2 * i - 1; j) {printf("*");}// 换行printf("\n");} }int main()…

好用的翻译工具

最近看到个好用的翻译工具&#xff0c;叫沉浸式翻译 沉浸式翻译 - 双语对照网页翻译插件 | PDF翻译 | 视频字幕翻译 我下载的是谷歌插件 点击下载插件会跳转到使用文档&#xff0c;跟着一步步操作即可 翻译的效果&#xff0c;我这里用的是免费版的&#xff0c;如果需要加强&…

Linux-CentOS的yum源

1、什么是yum yum是CentOS的软件仓库管理工具。 2、yum的仓库 2.1、yum的远程仓库源 2.1.1、国内仓库 国内较知名的网络源(aliyun源&#xff0c;163源&#xff0c;sohu源&#xff0c;知名大学开源镜像等) 阿里源:https://opsx.alibaba.com/mirror 网易源:http://mirrors.1…

el-table组件样式如何二次修改?

文章目录 前言一、去除全选框按钮样式二、表头颜色的修改 前言 ElementUI中的组件el-table表格组件提供了丰富的样式&#xff0c;有一个全选框的el-table组件&#xff0c;提供了全选框和多选。 一、去除全选框按钮样式 原本默认是有全选框的。假如有一些开发者&#xff0c;因…

一起学SysML v2规范(01)

1 00:00:01,560 --> 00:00:05,840 今天我们开始一个新的系列 2 00:00:06,690 --> 00:00:08,190 一起学SysML v2 3 00:00:08,200 --> 00:00:09,570 规范 4 00:00:15,770 --> 00:00:17,040 这里说一起学 5 00:00:17,050 --> 00:00:18,920 就是说我和大家一起学…

(9)下:学习与验证 linux 里的 epoll 对象里的 EPOLLIN、 EPOLLHUP 与 EPOLLRDHUP 的不同。小例子的实验

&#xff08;4&#xff09;本实验代码的蓝本&#xff0c;是伊圣雨老师里的课本里的代码&#xff0c;略加改动而来的。 以下是 服务器端的代码&#xff1a; 每当收到客户端的报文时&#xff0c;就测试一下对应的 epoll 事件里的事件标志&#xff0c;不读取报文内容&#xff0c;…

【Python】第七弹---Python基础进阶:深入字典操作与文件处理技巧

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、字典 1.1、字典是什么 1.2、创建字典 1.3、查找 key 1.4、新增/修改元素 1.5、删除元素 1.6、遍历…

[Linux]从零开始的STM32MP157 U-Boot移植

一、前言 在上一次教程中&#xff0c;我们了解了STM32MP157的启动流程与安全启动机制。我们还将FSBL的相关代码移植成功了。大家还记得FSBL的下一个步骤是什么吗&#xff1f;没错&#xff0c;就是SSBL&#xff0c;而且常见的我们将SSBL作为存放U-Boot的地方。所以本次教程&…

消息队列篇--原理篇--常见消息队列总结(RabbitMQ,Kafka,ActiveMQ,RocketMQ,Pulsar)

1、RabbitMQ 特点&#xff1a; AMQP协议&#xff1a;RabbitMQ是基于AMQP&#xff08;高级消息队列协议&#xff09;构建的&#xff0c;支持多种消息传递模式&#xff0c;如发布/订阅、路由、RPC等。多语言支持&#xff1a;支持多种编程语言的客户端库&#xff0c;包括Java、P…

家居EDI:Hom Furniture EDI需求分析

HOM Furniture 是一家成立于1977年的美国家具零售商&#xff0c;总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品&#xff0c;满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…