Linux程序开发(十二):线程与多线程同步互斥实现抢票系统

news2024/9/20 20:51:44

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊!

喜欢我的博客的话,记得点个红心❤️和小关小注哦!您的支持是我创作的动力!数据源存放在我的资源下载区啦!

Linux程序开发(十二):线程与多线程同步互斥实现抢票系统

目录

  • Linux程序开发(十二):线程与多线程同步互斥实现抢票系统
    • 题目:抢票系统
    • 题目描述:
    • 示例输入:
    • 示例输出:
    • 提示:
    • 解答:
    • 截图:

题目:抢票系统

题目描述:

某公司的演唱会门票正在热销中,为了让用户更好地体验购票过程,公司决定开启一个抢票系统。具体来说,用户可以在系统中选择想要购买的门票数量,系统会随机生成几个购票请求,并给出这些请求的优先级(优先级越高,越先处理)。每个请求需要购买一定数量的门票,如果门票数量已经不足,则该请求将会被拒绝。如果多个请求同时到达,需要按照优先级进行处理。在处理完一个请求后,系统需要输出当前剩余的门票数量。

请你使用Linux下的线程和多线程同步互斥知识,编写一个C程序实现这个抢票系统,要求满足以下条件:
1、系统需要启动两个线程,一个线程代表用户,另一个线程代表抢票程序。
2、用户可以通过命令行输入想要购买的门票数量,抢票程序会自动生成随机的购票请求,并给出优先级。
3、抢票程序需要使用线程池来处理请求,每个请求需要分配一个线程来处理。
4、抢票程序需要使用信号量和互斥锁等机制来实现线程间同步和互斥访问共享资源(如门票数量)。
5、在处理完每个请求后,抢票程序需要输出当前剩余的门票数量。
6、当所有的门票售出后,抢票程序需要结束运行。

示例输入:

请输入购票数量:10

示例输出:

当前剩余门票数量:90
当前剩余门票数量:85
当前剩余门票数量:75
当前剩余门票数量:70
当前剩余门票数量:65
当前剩余门票数量:60
当前剩余门票数量:53
当前剩余门票数量:48
当前剩余门票数量:38

提示:

可以使用Linux系统函数pthread_create()、pthread_join()、pthread_mutex_init()、pthread_mutex_lock()、pthread_mutex_unlock()和pthread_mutex_destroy()来创建和使用线程和互斥锁。
可以使用Linux系统函数sem_init()、sem_wait()、sem_post()和sem_destroy()来创建和使用信号量。

解答:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <semaphore.h>

#define TOTAL_TICKETS 100

// 定义全局变量和互斥锁、信号量
int tickets = TOTAL_TICKETS;
pthread_mutex_t mutex;
sem_t semaphore;

// 定义线程池结构体
typedef struct {
    int priority;
    int num_tickets;
} Request;

void* user_thread(void* arg) {
    // 输入购票数量
    int num_tickets;
    printf("请输入购票数量:");
    scanf("%d", &num_tickets);

    // 等待抢票线程结束
    struct timespec delay = {0, 500000000};  // 500ms
    clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);

    // 创建抢票请求
    Request* request = (Request*)malloc(sizeof(Request));
    request->priority = 0;  // 用户请求的优先级为最高
    request->num_tickets = num_tickets;

    // 抢票程序处理请求
    pthread_mutex_lock(&mutex);
    if (tickets >= num_tickets) {
        tickets -= num_tickets;
        printf("购票成功!当前剩余门票数量:%d\n", tickets);
    } else {
        printf("购票失败!当前剩余门票数量:%d\n", tickets);
    }
    pthread_mutex_unlock(&mutex);

    free(request);
    return NULL;
}

void* ticket_thread(void* arg) {
    Request* request = (Request*)arg;

    // 模拟处理请求的耗时操作
    struct timespec delay = {request->priority, 0};
    clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);

    sem_wait(&semaphore);  // 请求抢到票之前等待信号量
    pthread_mutex_lock(&mutex);
    if (tickets >= request->num_tickets) {
        tickets -= request->num_tickets;
        printf("当前剩余门票数量:%d\n", tickets);
    } else {
        printf("请求被拒绝!当前剩余门票数量:%d\n", tickets);
    }
    pthread_mutex_unlock(&mutex);
    sem_post(&semaphore);  // 抢到票后释放信号量

    free(request);
    return NULL;
}
int main() {
    // 初始化互斥锁和信号量
    pthread_mutex_init(&mutex, NULL);
    sem_init(&semaphore, 0, 1);
    // 创建线程池
    pthread_t threads[10];
    // 创建抢票线程
    for (int i = 0; i < 10; i++) {
        Request* request = (Request*)malloc(sizeof(Request));
        request->priority = rand() % 10 + 1;  // 随机生成优先级
        request->num_tickets = rand() % 10 + 1;  // 随机生成购票数量
        pthread_create(&threads[i], NULL, ticket_thread, request);
        struct timespec delay = {0, 50000000};  // 50ms
        clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL); // 睡眠一段时间,防止随机数相同
    }
    // 创建用户线程
    pthread_t user_tid;
    pthread_create(&user_tid, NULL, user_thread, NULL);

    // 等待抢票线程结束
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }
    // 等待用户线程结束
    pthread_join(user_tid, NULL);
    // 清理资源
    pthread_mutex_destroy(&mutex);
    sem_destroy(&semaphore);
    return 0;
}

截图:

在这里插入图片描述
图 3.1 运行结果图

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

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

相关文章

Mongodb分布式id

1、分布式id使用场景 分布式ID是指在分布式系统中用于唯一标识每个元素的数字或字符串。在分布式系统中&#xff0c;各个节点或服务可能独立运行在不同的服务器、数据中心或地理位置&#xff0c;因此需要一种机制来确保每个生成的ID都是全局唯一的&#xff0c;以避免ID冲突。 …

Pytorch线性模型(Linear Model)

基本步骤 ①首先准备好数据集&#xff08;DataSet&#xff09; ②模型的选择或者设计&#xff08;Model&#xff09; ③进行训练&#xff08;Train&#xff09;大部分模型都需要训练&#xff0c;有些不需要。这一步后我们会确定不同特征的权重 ④推理&#xff08;inferring…

就业班 第三阶段(ELK) 2401--5.20 day1 ELK 企业实战 ES+head+kibana+logstash部署(最大集群)

ELKkafkafilebeat企业内部日志分析系统 1、组件介绍 1、Elasticsearch&#xff1a; 是一个基于Lucene的搜索服务器。提供搜集、分析、存储数据三大功能。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java开发的&#xff…

学习单向链表带哨兵demo

一、定义 在计算机科学中&#xff0c;链表是数据元素的线性集合&#xff0c;其每个元素都指向下一个元素&#xff0c;元素存储上并不连续。 1.可以分三类为 单向链表&#xff0c;每个元素只知道其下一个元素是谁 双向链表&#xff0c;每个元素知道其上一个元素和下一个元素 …

mySql从入门到入土

基础篇 在cmd中使用MYSQL的相关指令&#xff1a; net start mysql // 启动mysql服务 net stop mysql // 停止mysql服务 mysql -uroot -p1234//登录MYSQL&#xff08;-u为用户名-p为密码&#xff09; //登录参数 mysql -u用户名 -p密码 -h要连接的mysql服务器的ip地址(默认1…

记一次安卓“Low on memory“崩溃问题

前言 最近再调人脸识别算法相关demo,发现调试期间总是偶发性崩溃&#xff0c;捕获不到异常的那种&#xff0c;看日志发现原因是Low on memory&#xff0c;一开始还疑惑 App内存不够应该是OOM啊,怎么会出现这种问题&#xff0c;百思不得其解&#xff0c;直到我打开了 Android s…

Git 仓库中 -- 代码冲突产生、定位、解决的流程

目录 前置知识1 工具环境2 冲突的产生2.1 仓库中的源代码2.2 人员 A 首先更改代码2.3 人员 B 更改代码&#xff0c;产生冲突2.3.1 第一次错误提示&#xff1a;2.3.2 第二次错误提示&#xff1a; 3 查看冲突4 手动解决冲突4.1 方式一4.2 方式二&#xff08;tortoisegit&#xff…

Vitis HLS 学习笔记--控制驱动任务示例

目录 1. 简介 2. 代码解析 2.1 kernel 代码回顾 2.2 功能分析 2.3 查看综合报告 2.4 查看 Schedule Viewer 2.5 查看 Dataflow Viewer 3. Vitis IDE的关键设置 3.1 加载数据文件 3.2 设置 Flow Target 3.3 配置 fifo 深度 4. 总结 1. 简介 本文对《Vitis HLS 学习…

CSAPP(datalab)解析

howManyBits /* howManyBits - 返回用二进制补码表示x所需的最小位数* 示例: howManyBits(12) 5* howManyBits(298) 10* howManyBits(-5) 4* howManyBits(0) 1* howManyBits(-1) 1* howManyBits(0x80000000) …

【Linux】TCP协议【上】{协议段属性:源端口号/目的端口号/序号/确认序号/窗口大小/紧急指针/标记位}

文章目录 1.引入2.协议段格式4位首部长度16位窗口大小32位序号思考三个问题【demo】标记位URG: 紧急指针是否有效提升某报文被处理优先级【0表示不设置1表示设置】ACK: 确认号是否有效PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走RST: 对方要求重新建立连接; 我们把携带R…

【C++】详解AVL树——平衡二叉搜索树

个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 祝福语&#xff1a;愿你拥抱自由的风 目录 二叉搜索树 AVL树概述 平衡因子 旋转情况分类 左单旋 右单旋 左右双旋 右左双旋 AVL树节点设计 AVL树设计 详解单旋 左单旋 右单旋 详解双旋 左右双旋 平衡因子情况如…

远程工作的数据安全挑战和解决策略

随着远程工作的普及&#xff0c;数据安全面临了前所未有的挑战。企业在应对这些挑战时&#xff0c;必须采取切实有效的策略来保护敏感信息。以下是远程工作数据安全的主要挑战和相应的解决策略&#xff1a; 数据安全挑战 设备丢失或被盗&#xff1a;员工在外工作时&#xff0c…

从 0 开始本地部署大语言模型

1、准备 ● Ollama&#xff1a;ollama.com ● Docker&#xff1a;https://docs.openwebui.com/ 2、下载 Ollama 进入 Ollama 官网&#xff0c;点击 Download 。 下载完成后&#xff0c;双击安装&#xff0c;什么都不需要勾选&#xff0c;直接下一步即可。安装完成&#xf…

算法之堆排序

堆排序是一种基于比较的排序算法&#xff0c;通过构建二叉堆&#xff08;Binary Heap&#xff09;&#xff0c;可以利用堆的性质进行高效的排序。二叉堆是一个完全二叉树&#xff0c;可以有最大堆和最小堆两种形式。在最大堆中&#xff0c;父节点的值总是大于或等于其子节点的值…

【TB作品】stm32单片机读取DS2401程序

DS2401是由Analog Devices公司生产的一种硅序列号芯片&#xff0c;它提供了一个绝对唯一的64位ROM识别码&#xff0c;用于确保可追溯性。以下是对DS2401器件的分析&#xff1a; 特点和优势&#xff1a; 唯一性&#xff1a;每个DS2401芯片都有一个独一无二的64位注册码&#x…

Redis机制-Redis缓存穿透,击穿,雪崩理解等问题的理解和学习

目录 一 缓存穿透问题 二 缓存击穿问题 三 缓存雪崩问题&#xff1a; 图1 正常的Redis缓存流程 一 缓存穿透问题 我们都知道Redis是一个存储键值对的非关系型数据库&#xff0c;那么当用户进行查询的时候&#xff0c;势必会从前端发起请求&#xff0c;从而数据从Redis缓存…

MySQL笔记第三天(从小白到入门)

文章目录 MySQL笔记SQL语言介绍数据库系统关系型数据库非关系型数据库SQL和数据库系统的关系数据库系统架构 MySQL的介绍概念MySQL的版本 MySQL的DDL操作-重点基本数据库操作基本表操作 MySQL的DML操作-重点insert-插入数据update-更新数据delete-删除数据 MySQL的约束-了解概述…

RabbitMQ .NET

setup rabbitmq docker run --namerabbit -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USERadmin -e RABBITMQ_DEFAULT_PASSxxx -d rabbitmq:management ip:15672 login nuget RabbitMQ.Client Send //1.1.实例化连接工厂 var factory new ConnectionFactory() …

WordPress搭建流程

1. 简介 WordPress 是一个 PHP 编写的网站制作平台。WordPress 本身免费,并且拥有众多的主题可以使用,适合用于搭建个人博客、公司官网、独立站等。 2. 环境准备 2.1 WordPress 下载 WordPress 可以在 Worpress中文官网 下载(如果后续要将后台调成中文的话,一定要从中文…

虚拟局域网(VLAN)

关键词&#xff1a;veth、vlan、bridge、iptables、nat、tcpdump、icmp、cidr、arp、路由表、计算机网络协议栈 前言 在过去的几十年里&#xff0c;互联网发展得非常快。许多新兴技术迅速崛起&#xff0c;也有不少曾经的主流技术被淘汰。然而&#xff0c;有些技术因为其基础性…