【Linux操作系统】信号量实现生生产者消费者模型

当涉及到多线程编程时,经常会遇到生产者消费者问题。在Linux系统编程中,我们可以使用信号量来实现生产者消费者模型,以确保线程之间的同步和互斥。

在这里插入图片描述

文章目录

    • 什么是生产者消费者问题?
    • 使用信号量实现生产者消费者模型
      • 信号量的原理
      • 信号量的函数
      • 示例代码解释
    • 结论

什么是生产者消费者问题?

生产者消费者问题是一个经典的多线程编程问题,涉及到两种类型的线程:生产者和消费者。生产者线程生成数据并将其放入共享缓冲区,而消费者线程从共享缓冲区中取出数据并进行处理。生产者和消费者之间需要进行同步,以确保生产者不会在缓冲区已满时继续生产数据,消费者不会在缓冲区为空时继续消费数据。

使用信号量实现生产者消费者模型

在Linux系统编程中,我们可以使用信号量来实现生产者消费者模型。信号量是一种用于多线程编程中实现同步和互斥的机制。它可以用来解决生产者消费者问题、读者写者问题、哲学家就餐问题等多线程编程中的经典问题。

信号量的原理

信号量是一个计数器,用来控制对共享资源的访问。当一个线程需要访问共享资源时,它会先检查信号量的值。如果信号量的值大于0,则表示有可用的资源,线程可以继续执行。如果信号量的值为0,则表示没有可用的资源,线程需要等待。

当一个线程访问完共享资源后,它会将信号量的值减1,表示使用了一个资源。当一个线程释放共享资源后,它会将信号量的值加1,表示释放了一个资源。其他线程可以通过检查信号量的值来判断是否可以继续执行。

信号量的函数

在Linux系统编程中,我们可以使用sem_init()sem_wait()sem_post()sem_destroy()等函数来操作信号量。

  • int sem_init(sem_t *sem, int pshared, unsigned int value):初始化信号量。sem是指向信号量的指针,pshared指定信号量的类型,value指定信号量的初始值。如果成功,返回0;否则,返回-1。

  • int sem_wait(sem_t *sem):等待信号量。如果信号量的值大于0,则将信号量的值减1,并继续执行;如果信号量的值为0,则线程需要等待。如果成功,返回0;否则,返回-1。

  • int sem_post(sem_t *sem):释放信号量。将信号量的值加1,表示释放了一个资源。如果成功,返回0;否则,返回-1。

  • int sem_destroy(sem_t *sem):销毁信号量。如果成功,返回0;否则,返回-1。

示例代码解释

下面是一个使用信号量实现生产者消费者模型的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>#define BUFFER_SIZE 10int buffer[BUFFER_SIZE];
sem_t empty;
sem_t full;
pthread_mutex_t mutex;void *producer(void *arg) {int item;while (1) {item = rand() % 100;  // 生成随机数据sem_wait(&empty);  // 等待空闲空间pthread_mutex_lock(&mutex);  // 加锁// 将数据放入缓冲区// ...pthread_mutex_unlock(&mutex);  // 解锁sem_post(&full);  // 通知有数据可用}
}void *consumer(void *arg) {int item;while (1) {sem_wait(&full);  // 等待有数据可用pthread_mutex_lock(&mutex);  // 加锁// 从缓冲区取出数据并进行处理// ...pthread_mutex_unlock(&mutex);  // 解锁sem_post(&empty);  // 通知有空闲空间}
}int main() {pthread_t producerThread, consumerThread;// 初始化信号量和互斥锁sem_init(&empty, 0, BUFFER_SIZE);sem_init(&full, 0, 0);pthread_mutex_init(&mutex, NULL);// 创建生产者线程和消费者线程pthread_create(&producerThread, NULL, producer, NULL);pthread_create(&consumerThread, NULL, consumer, NULL);// 等待线程结束pthread_join(producerThread, NULL);pthread_join(consumerThread, NULL);// 销毁信号量和互斥锁sem_destroy(&empty);sem_destroy(&full);pthread_mutex_destroy(&mutex);return 0;
}

在上面的代码中,我们使用了一个大小为BUFFER_SIZE的缓冲区来模拟共享资源。emptyfull是两个信号量,用于控制空闲空间和已存放数据的数量。mutex是一个互斥锁,用于保护对共享资源的访问。

生产者线程通过生成随机数据,并将数据放入缓冲区。在放入数据之前,它首先等待空闲空间的信号量empty,如果有空闲空间,则继续执行。放入数据后,它将已存放数据的信号量full加1。

消费者线程通过从缓冲区中取出数据,并进行处理。在取出数据之前,它首先等待已存放数据的信号量full,如果有数据可用,则继续执行。取出数据后,它将空闲空间的信号量empty加1。

结论

信号量是一种用于多线程编程的同步工具,可以用来解决生产者消费者模型中的同步和互斥问题。通过使用信号量,我们可以控制线程的执行顺序,保证线程之间的互斥和同步。

在Linux系统编程中,使用信号量需要包含头文件<semaphore.h>,并通过以下函数来操作信号量:

  • int sem_init(sem_t *sem, int pshared, unsigned int value):初始化信号量。sem是指向信号量的指针,pshared指定信号量的共享方式,value是信号量的初始值。如果成功,返回0;否则,返回-1。

  • int sem_wait(sem_t *sem):等待信号量。如果信号量的值大于0,则将信号量的值减1,表示占用了一个资源。如果信号量的值为0,则线程需要等待。如果成功,返回0;否则,返回-1。

  • int sem_post(sem_t *sem):释放信号量。将信号量的值加1,表示释放了一个资源。如果成功,返回0;否则,返回-1。

  • int sem_destroy(sem_t *sem):销毁信号量。如果成功,返回0;否则,返回-1。

通过使用信号量和互斥锁,我们可以实现生产者消费者模型,并确保生产者和消费者之间的互斥和同步。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iPhone 14 Plus与iPhone 14 Pro:你应该买哪一款

又到了iPhone季,这意味着你可能会在几种不同的机型之间左右为难,无法决定买哪一款。更令人困惑的是,苹果推出的iPhone变体——iPhone 14 Plus,只比老款iPhone 14 Pro低100美元。 有这么多选择,你可能想知道哪款iPhone最适合你。你应该买一部大屏幕的iPhone 14 Plus并节省…

Jenkins自动化部署-Jenkins的安装

首先我们需要安装docker 安装 yum-utils包 yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken 设置镜像地址 yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce…

【ES6】Promise的入门介绍

Promise 是 JavaScript 中的一个对象&#xff0c;用于处理异步操作。Promise 对象代表一个最终可能完成&#xff08;并得到结果&#xff09;或失败&#xff08;并被拒绝&#xff09;的操作&#xff0c;以及其结果的值。 一个 Promise 有三种状态&#xff1a; Pending&#xf…

包含文心一言在内的首批国产大模型 全面开放

8月31起&#xff0c;国内 11 家通过《生成式人工智能服务管理暂行办法》备案的 AI 大模型产品将陆续上线&#xff0c;面向全社会开放。北京 5 家大模型产品分别是百度的 “文心一言”、抖音的 “云雀”、百川智能的 “百川大模型”、清华系 AI 公司智谱华章旗下的 “智谱清言”…

vue3 Table 分页保留选中状态

//指定id值,数据更新之后保留之前选中的数据 const getRowKeys (row) > {return row.siteId; }; // 这存的是选中的数据 const userSelectionChange (values) > {state.selectedData [...values]; }; // 两个数组对比&#xff0c;判断表格中的数据是否开启选中 cons…

chrono学习(一)

我想用chrono进行沙土的仿真&#xff0c;首先学习demo_GPU_ballCosim.cpp&#xff0c;这个例子仿真了一些沙土的沉降过程。 首先&#xff0c;运行编辑完成的文件demo_GPU_ballCosim&#xff1a; (base) eowyneowyn-MS-7D20:~/build_chrono/bin$ ./demo_GPU_ballCosim 运行完得…

Spring源码分析(十)Bean实例化(下)

目录 1.1 循环依赖1.2 属性填充1.2.1 populateBean方法1.2.2 initializeBean方法执行Aware方法执行BeanPostProcessor后置处理器的前置处理方法执行初始化方法执行BeanPostProcessor后置处理器的后置处理方法&#xff1a;postProcessAfterInitialization()&#xff0c;允许对be…

MySQL数据库基本操作

目录 一、数据库中常用的数据类型 二、常用命令与操作 1.DDL数据库定义语言 1、登录用户的数据库 2、查看当前服务器中的数据库 3、切换/进入数据库 并 查看数据库中包含的表 4、查看数据库中表的结构 5、创建数据库 7、展示创建数据表时的结构 8、创建表&#xff0c…

Linux 三剑客

grep grep主打的就是查找功能 &#xff0c;它能够在一个或者多个文件中搜索某一特定的字符模式。 grep的语法 grep [选项] 模式 文件名 先说选项&#xff1a; 1.选项 要么是正则要么是字符串 -c 列出共出现多少次 -i 忽略大小写 -n 在前面列出行号 -v …

阿里云centos9stream安装宝塔+vscode(code-server)集成云端开发环境

一、 安装宝塔面板 官网 https://www.bt.cn/new/download.htm 题外话&#xff1a;虽然感觉现在宝塔没以前好用了&#xff0c;而且有centos7、8 mysql编译导致OOM服务器挂掉无法ssh登录的情况&#xff0c;但他还是远程管理服务器的好选择&#xff0c;提示宝塔只支持最新的centos…

常见矿石材质鉴定VR实训模拟操作平台提高学员的学习效果和实践能力

随着“元宇宙”概念的不断发展&#xff0c;在矿山领域中&#xff0c;长期存在传统培训内容不够丰富、教学方式单一、资源消耗大等缺点&#xff0c;无法适应当前矿山企业发展需求的长期难题。元宇宙企业借助VR虚拟现实、web3d开发和计算机技术构建的一个虚拟世界&#xff0c;为用…

SpringBoot虚拟路径映射

要求&#xff1a;访问&#xff1a;127.0.0.1/image/下的文件时&#xff0c;自动映射到真实路径&#xff1a;D:Files\。 virtualFileDepositPath: /image/** realityFileDepositPath: C:\Users\xin\Desktop\imgCreate\Files\ import org.springframework.beans.factory.annota…

编写c语言程序调用openssl编译出的动态链接库

文章目录 一、编译生成链接库二、示例一&#xff1a;调用RAND_bytes函数三、示例二&#xff1a;调用SHA256 一、编译生成链接库 下载安装openssl并编译生成链接库的过程在我的另一篇文章中已经详细说明了&#xff1a;Ubuntu中安装OpenSSL 此外&#xff0c;我们还需要提前了解…

微服务之Nacos

1 版本说明 官网地址&#xff1a; https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 1.1 2021.x 分支 适配 SpringBoot 2.4, Spring Cloud 2021.x 版本及以上的Spring Cloud Alibaba 版本如下表&#xff08;最新版本用*标记&am…

RHCE——十三、Shell自动化运维编程基础

Shell 一、为什么学习和使用Shell编程二、Shell是什么1、shell起源2、查看当前系统支持的shell3、查看当前系统默认shell4、Shell 概念 三、Shell 程序设计语言1、Shell 也是一种脚本语言2、用途 四、如何学好shell1、熟练掌握shell编程基础知识2、建议 五、Shell脚本的基本元素…

docker-compose安装opengauss数据库

文章目录 1. docker-compose.yaml2. 部署3. 卸载4. 连接 1. docker-compose.yaml mkdir -p /root/i/docker-compose/opengauss && cd /root/i/docker-compose/opengausscat <<EOF> /root/i/docker-compose/opengauss/docker-compose.yaml version: 3 service…

计算机竞赛 基于机器视觉的停车位识别检测

简介 你是不是经常在停车场周围转来转去寻找停车位。如果你的车辆能准确地告诉你最近的停车位在哪里&#xff0c;那是不是很爽&#xff1f;事实证明&#xff0c;基于深度学习和OpenCV解决这个问题相对容易&#xff0c;只需获取停车场的实时视频即可。 该项目较为新颖&#xf…

MongoDB实验——在MongoDB集合中查找文档

在MongoDB集合中查找文档 一、实验目的二、实验原理三、实验步骤1.启动MongoDB数据库、启动MongoDB Shell客户端2.数据准备-->person.json3.指定返回的键4 .包含或不包含 i n 或 in 或 in或nin、$elemMatch&#xff08;匹配数组&#xff09;5.OR 查询 $or6.Null、$exists7.…

【JavaScript精通之道】掌握数据遍历:解锁现代化遍历方法,提升开发效率!

​ &#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 &#x1f4da; 前言 &#x1f4d8; 1. reduce方法 &#x1f4d8; 2. forEach方法 &#x1f4d8; 3. map方法…