Linux 多线程 生产者消费者 问题

在 Linux 系统中,生产者和消费者问题是一个经典的多线程同步问题,用于描述如何在多线程环境中协调多个线程对共享资源的访问。这个问题通常涉及两个类型的线程:生产者线程和消费者线程。生产者线程负责生成数据并将其放入缓冲区,而消费者线程则从缓冲区中取出数据进行处理。

生产者和消费者问题的基本概念

  1. 生产者(Producer):

    • 生成数据并将其放入共享缓冲区。
    • 生产者必须在缓冲区满时等待,直到有空间可用。
  2. 消费者(Consumer):

    • 从共享缓冲区中取出数据进行处理。
    • 消费者必须在缓冲区空时等待,直到有数据可用。

共享资源和同步机制

为了确保线程安全并避免竞态条件,生产者和消费者通常使用以下同步机制:

  1. 互斥锁(Mutex):

    • 用于确保只有一个线程可以在任何给定时间内访问共享缓冲区。
    • 通过锁定和解锁操作来实现。
  2. 条件变量(Condition Variable):

    • 用于让线程在某些条件下等待或唤醒。
    • 生产者在缓冲区不满时发信号唤醒消费者,消费者在缓冲区有数据时发信号唤醒生产者。

让我们用一个更生动的例子来解释生产者-消费者问题中的条件变量和互斥锁的工作机制。

例子:餐厅的厨师和服务员

想象一下,有一个餐厅,里面有一个厨房(缓冲区)和一个用餐区。餐厅有两种工作人员:厨师(生产者)和服务员(消费者)。他们之间的协调就像在处理生产者-消费者问题。

场景设置
  • 厨房有一个有限大小的桌子(缓冲区),桌子上可以放一定数量的菜(数据)。
  • 厨师做菜(生产数据)并把菜放到桌子上。
  • 服务员从桌子上拿菜(消费数据)并把菜送到顾客那里。
  • 如果桌子满了,厨师就不能放菜,需要等待服务员拿走菜。
  • 如果桌子空了,服务员就不能拿菜,需要等待厨师放菜。
具体流程
  1. 厨师做菜并放在桌子上:

    • 厨师首先检查桌子上有没有空位。
    • 如果桌子满了,厨师就等待(进入等待状态)。
    • 如果桌子有空位,厨师把菜放在桌子上,然后通知服务员桌子上有新菜了。
    • 厨师然后继续做下一道菜。
  2. 服务员拿菜并送到顾客那里:

    • 服务员首先检查桌子上有没有菜。
    • 如果桌子空了,服务员就等待(进入等待状态)。
    • 如果桌子上有菜,服务员拿走菜并送到顾客那里,然后通知厨师桌子上有空位了。
    • 服务员然后继续拿下一道菜。

代码对应的具体场景

以下代码片段展示了这个过程:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define BUFFER_SIZE 10

int buffer[BUFFER_SIZE];
int count = 0;

pthread_mutex_t mutex;
pthread_cond_t cond_producer;
pthread_cond_t cond_consumer;

void* producer(void* arg) {
    while (1) {
        // 生成数据(例如:随机数)
        int item = rand() % 100;

        pthread_mutex_lock(&mutex);

        // 等待缓冲区有空位
        while (count == BUFFER_SIZE) {
            pthread_cond_wait(&cond_producer, &mutex);
        }

        // 将数据放入缓冲区
        buffer[count++] = item;
        printf("Produced: %d\n", item);

        // 通知消费者有数据可用
        pthread_cond_signal(&cond_consumer);
        
        pthread_mutex_unlock(&mutex);

        // 模拟生产时间
        sleep(1);
    }
}

void* consumer(void* arg) {
    while (1) {
        pthread_mutex_lock(&mutex);

        // 等待缓冲区有数据
        while (count == 0) {
            pthread_cond_wait(&cond_consumer, &mutex);
        }

        // 从缓冲区取出数据
        int item = buffer[--count];
        printf("Consumed: %d\n", item);

        // 通知生产者有空位可用
        pthread_cond_signal(&cond_producer);
        
        pthread_mutex_unlock(&mutex);

        // 模拟消费时间
        sleep(1);
    }
}

int main() {
    pthread_t producer_thread, consumer_thread;

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond_producer, NULL);
    pthread_cond_init(&cond_consumer, NULL);

    pthread_create(&producer_thread, NULL, producer, NULL);
    pthread_create(&consumer_thread, NULL, consumer, NULL);

    pthread_join(producer_thread, NULL);
    pthread_join(consumer_thread, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond_producer);
    pthread_cond_destroy(&cond_consumer);

    return 0;
}

运行结果:

解释
  1. 互斥锁(pthread_mutex_t mutex)

    • 互斥锁就像厨房的门,确保只有一个厨师或服务员可以进出厨房,以防止混乱。
  2. 条件变量(pthread_cond_t cond_producer 和 pthread_cond_t cond_consumer)

    • 条件变量就像门口的信号灯。
    • cond_producer 是厨师用来等待服务员拿走菜的信号灯。
    • cond_consumer 是服务员用来等待厨师放菜的信号灯。
  3. 厨师(producer)

    • 厨师检查厨房的桌子(缓冲区)是否满了。
    • 如果满了,厨师等待(等待cond_producer信号)。
    • 如果有空位,厨师放菜在桌子上,并通知服务员(发送cond_consumer信号)。
    • 然后,厨师离开厨房(解锁互斥锁),继续做下一道菜。
  4. 服务员(consumer)

    • 服务员检查厨房的桌子(缓冲区)是否有菜。
    • 如果桌子空了,服务员等待(等待cond_consumer信号)。
    • 如果有菜,服务员拿走菜,并通知厨师(发送cond_producer信号)。
    • 然后,服务员离开厨房(解锁互斥锁),继续送菜给顾客。

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

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

相关文章

大数据之Schedule调度错误(一)

当我们在利用ooize发起整个任务的调度过程中,如果多个调度任务同时运行并且多个调度任务操作了相同的表,那么就会出现如下的错误关系: Invalid path hdfs://iZh5w01l7f8lnog055cpXXX:8000/user/admin/xxx: No files matching path hdfs://iZh5w01l7f8lnog055cpXXX:8000/user/ad…

VS2017配置OpenCV4.5.1

VS2017配置OpenCV 一、下载OpenCV二、配置OpenCV的电脑环境变量三、配置visual Studio添加路径复制文件到C盘 四、如何使用注意运行时选择Debug x64 五、报错&#xff1a;VSOpencv出现&#xff1a;xxx处有未经处理的异常: Microsoft C 异常: cv::Exception&#xff0c;位于内存…

iLogtail 2.0 重大升级,端上支持 SPL

作者&#xff1a;太业 流式处理语言发展 早期流式处理概念&#xff1a; 20 世纪 70 年代&#xff0c;编程语言如 APL 提供了对数组的流式操作&#xff0c;这可以看作是流式处理语法的早期形式。管道&#xff08;Pipes&#xff09;概念在 UNIX 系统中的引进使得可以通过命令行将…

opencv进阶 ——(十)图像处理之基于dlib人脸检测与识别

Dlib是一个功能丰富的C库&#xff0c;设计用于构建复杂的软件系统&#xff0c;尤其在机器学习、计算机视觉和数值计算等领域有着广泛的应用。以下是对Dlib的简要介绍&#xff1a; 特性&#xff1a; 机器学习算法&#xff1a;Dlib包含了各种机器学习算法&#xff0c;如支持向量机…

友思特应用 | 慧眼识珠:如何实现无障碍高光谱成像?

导读 近红外相机可帮助人眼捕捉不同材料之间光谱特征的微小差异。友思特 Monarch 微型可调近红外相机以其小体积、低成本、高性能&#xff0c;3步即可快速实现各种材料的分类应用。 多光谱成像 每个物品都是由不同的化学物质组成的&#xff0c;这些化学物质的反射随光谱带的不…

机器学习18个核心算法模型

1. 线性回归&#xff08;Linear Regression&#xff09; 用于建立自变量&#xff08;特征&#xff09;和因变量&#xff08;目标&#xff09;之间的线性关系。 核心公式&#xff1a; 简单线性回归的公式为&#xff1a; , 其中 是预测值&#xff0c; 是截距&#xff0c; 是斜…

ASCE(美国土木工程师学会)文献校外去哪里查找下载

今天要讲的数据库是ASCE&#xff08;美国土木工程师学会&#xff09;&#xff0c;该数据库每年出版5万多页的专业期刊、杂志、会议录、专著、技术报告、实践手册和标准等。目前&#xff0c;ASCE数据库中包含35种期刊(1983年至今)、近700卷会议录( 1996年至今)、Civil Engineeri…

10分钟了解KEDA高效弹性伸缩方案

文章目录 为什么需要 KEDA &#xff1f;KEDA 的原理哪些场景适合使用 KEDA &#xff1f;微服务多级调用任务执行&#xff08;生产者与消费者&#xff09;周期性规律 配置实践KEDA安装helm 方式安装 策略配置scaledobject 对象说明 问题记录 为什么需要 KEDA &#xff1f; HPA …

五、nodejs存储图片

nodejs存储图片 // 静态托管和数据库创建 创建数据库 新建Public进行静态托管 新建个img的文件夹 在index.js里 // 托管静态 app.use(/public, express.static(./Public))//托管静态资源 /*** 1.引入一个express框架* 2.在加载所有服务模块前&#xff0c;要先连接数据库* …

AST 在前端开发中的应用与实践:从代码分析到自动化转换

抽象语法树&#xff08;AST&#xff0c;Abstract Syntax Tree&#xff09;在前端开发中有着广泛的应用。它是编译器和工具链的核心组件&#xff0c;使得代码分析、转换、优化等操作成为可能。在前端开发中&#xff0c;AST 主要用于代码编译和转译、代码优化、代码分析、代码格式…

vue对图片进行裁剪

安装依赖&#xff1a; npm install cropperjs -save <template><div class"bigBox"><h3>预览</h3><!-- 裁剪按钮--><el-button click"sureSava">裁剪</el-button><el-button click"confirm">确…

元宇宙3D品牌营销虚拟场景提升客户对企业的黏性

在这个充满创意与想象的3D元宇宙时代&#xff0c;我们为您推出了全新的3D元宇宙场景在线制作编辑平台&#xff0c;让您轻松构建专属的虚拟展厅&#xff0c;展现无限可能。 3D元宇宙场景在线制作编辑平台允许您快速完成空间设计&#xff0c;根据您的个性化需求&#xff0c;自由设…

1.1 QT随手简记(一)

QT学习篇1 1. QT简介 Qt是一个跨平台的库&#xff0c;它提供了丰富的功能&#xff0c;用于开发GUI应用程序、桌面应用程序、移动应用程序和嵌入式应用程序。Qt由Qt公司维护&#xff0c;是一个开源项目&#xff0c;支持多种操作系统&#xff0c;包括Windows、Linux、Mac OS等。…

Django路由与会话深度探索:静态、动态路由分发,以及Cookie与Session的奥秘

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

clickhouse(十五、存储优化实践)

文章目录 背景问题定位优化方式排序键设计写入顺序压缩算法 DoubleDeltaLowCardinality避免使用Nullable 总结 背景 clickhouse集群容量告警&#xff0c;项目中某些表占据大量的存储空间&#xff0c;借此机会对ck的存储优化进行实践学习&#xff0c;并通过多种方式测试验证优化…

元宇宙NFG交易市场:减少出入金的税和消泡沫

在元宇宙的宏伟画卷中&#xff0c;NFG&#xff08;非同质化商品&#xff09;以其独特魅力逐渐崭露头角&#xff0c;成为连接现实世界与数字世界的桥梁。NFG不仅仅是一种商品&#xff0c;更是一种创新的商业模式&#xff0c;为资金的流动与税收优惠带来了新的可能。 首先&#…

QT error: allocation of incomplete type ‘Ui::Server‘

目录 前言 报错内容&#xff1a; 过程解析&#xff1a; 原因分析&#xff1a; daisy.skye的博客 QT合集http://t.csdnimg.cn/wEVbu 前言 最近又开始需要做上位机了&#xff0c;要知道qt上位机对我来说已经3年没有接触了&#xff0c;最开始接触还是毕业时工作中的简单学习和…

【预计IEEE出版】第四届电子信息工程与计算机技术国际学术会议(EIECT 2024)

第四届电子信息工程与计算机技术国际学术会议&#xff08;EIECT 2024&#xff09; 2024 4th International Conference on Electronic Information Engineering and Computer Technology 2024年11月15-17日 | 中国 深圳 #往届均已成功见刊、EI检索;先投稿&#xff0c;先送审…

CSS学习|css三种导入方式、基本选择器、层次选择器、结构伪类选择器、属性选择器、字体样式、文本样式

第一个css程序 css程序都是在style标签中书写 打开该网页&#xff0c;可以看到h1标签中的我是标题被渲染成了红色 可以在同级目录下创建一个css目录&#xff0c;专门存放css文件&#xff0c;可以和html分开编写 然后在html页面中&#xff0c;利用link标签以及css文件地址&…

【AI大模型】基于Langchain和Openai借口实现英文翻译中文应用

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680; 文章简介 &#xff1a;本专栏后续将持续更新大模型相关文章&#xff0c;从开发到微调到应用&#xff0c;需要下载好的模型包可私。 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 目…