Linux系统---图书管理中的同步问题

顾得泉:个人主页
个人专栏:《Linux操作系统》 《C/C++》 《LeedCode刷题》
键盘敲烂,年薪百万!
一、问题描述
(1)图书馆阅览室最多能够容纳N(N=5)名学生,若有更多学生想进入阅览室,必须等到阅览室中有同学退出之后才能进入。
(2)阅览室有一名管理员。早到的同学必须等管理员开门之后才能进入,管理员必须等到所有同学都退出之后才能关门。
请你用信号量实现上述问题。
二、问题分析
(1)将在“阅览室读书”看做一个临界区,该临界区最多只允许N名学生进入。把每个“学生”建模为一个线程,这是一个互斥问题。于是可以设计一个初值为N的信号量,实现互斥。
(2)管理员需要与第一个学生同步,即第一个学生等待管理员开门;管理员也需要与最后一名学生同步,即管理员等待最后一名学生退出之后,才能关闭图书馆。因此可以实现一个学生计数,实现条件同步。
三、命名规则
(1)用Student和Manager分别表示学生和管理员线程名。
(2)Student包括三个操作:Checkin( )(刷入)、Reading( )(阅读)、checkout( )(刷出)
(3)Manager包括三个操作:OpenDoor( )(开门)、CloseDoor( )(关门)、manage( )
四、具体实现
1. test.c文件
test.c文件是一个模拟学生进出教室的多线程程序。它使用了信号量(semaphore)来实现同步和互斥。
首先,定义了一些全局变量:
ns表示当前正在教室的学生数量。mutex用于保护对ns的访问。room用于限制教室的最大容量。wfm和wfs分别表示等待进入教室和等待离开教室的信号量。fetch表示等待学生进入教室的信号量。flag表示是否已经有学生进入教室。
接下来,定义了两个函数:
student(void* i)是每个学生的线程函数。它接收一个参数i,表示学生的编号。manager(void *arg)是管理线程的函数。它不需要参数。
在 student 函数中,首先打印出学生进入教室的信息。然后,通过调用 P(&fetch) 来请求获取 fetch 信号量,表示有学生准备进入教室。接着,通过调用 P(&mutex) 来请求获取 mutex 信号量,以保护对 ns 的访问。然后,根据当前的学生数量和是否有学生已经进入教室,执行相应的操作。最后,释放 mutex 信号量,并通过调用 sleep(1) 让当前线程暂停一段时间,模拟学生进入教室的过程。然后,打印出学生离开教室的信息,并释放其他信号量和变量。
在 manager 函数中,首先打印出管理打开教室的信息。然后,通过调用 V(&wfm) 来释放 wfm 信号量,表示有学生可以进入教室。接着,打印出管理等待所有学生离开教室的信息。然后,通过调用 P(&wfs) 来请求获取 wfs 信号量,表示所有学生都已经离开教室。最后,打印出管理关闭教室的信息。
在 main 函数中,首先初始化了所有的信号量。然后,创建了多个学生线程,每个线程对应一个学生编号。接着,创建了一个管理线程。最后,使用 pthread_exit(NULL) 退出主线程。
#include<semaphore.h>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include"ch4-PV.h"#define N 5unsigned int ns = 0;
sem_t mutex;
sem_t room;
sem_t wfm;
sem_t wfs;
sem_t fetch;
int flag = 0;void *student(void* i)
{int id = (int)i;printf("Student %i is entring...\n",id);P(&fetch);ns++;P(&mutex);if(ns == 1 && flag ==0){P(&wfm);P(&room);flag = 1;printf("The 1st student %i has been entered.\n",id);}else{P(&room);printf("The student %i has been entered\n",id);}V(&mutex);sleep(1);printf("The student %i is going to leave...\n",id);P(&mutex);ns--;if(ns == 0){V(&wfs);printf("The last student left.\n");}elseprintf("The student %i has left.\n",id);V(&room);V(&mutex);V(&fetch);
}void *manager(void *arg)
{printf("The manager opens the door.\n");V(&wfm);printf("The manager is waiting for all student leaves.\n");P(&wfs);printf("The manager closes the door.\n");
}int main()
{sem_init(&wfm,0,0);sem_init(&fetch,0,5);sem_init(&wfs,0,0);sem_init(&mutex,0,1);sem_init(&room,0,5);pthread_t tid;for(int i = 1; i <= N; i++)pthread_create(&tid,NULL,student,(void *)i);pthread_create(&tid,NULL,manager,(void *)NULL);pthread_exit(NULL);return 0;
}
2. ch4-PV.c文件
这段代码是一个简单的信号量实现,用于实现生产者消费者问题。其中包含了两个函数:P() 和 V()。
- P(sem_t *s) 函数用于等待信号量。如果信号量的值大于0,则将信号量的值减1并返回;否则,该函数会阻塞,直到信号量的值变为大于0。
- V(sem_t *s) 函数用于释放信号量。将信号量的值加1,并唤醒一个等待该信号量的线程。
#include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include"ch4-PV.h"void P(sem_t *s)
{if(sem_wait(s)<0)printf("P error");
}void V(sem_t *s)
{if(sem_post(s)<0)printf("V error");
}
3. ch4-PV.h文件
这段代码定义了相应的头文件。
#include<semaphore.h>
#include<unistd.h>void P(sem_t *s);
void V(sem_t *s);
4. makeflie文件
这是一个Makefile文件,用于编译和清理生成的可执行文件和目标文件。(之前的文章对此有过相应的讲解)
test:test.o ch4-PV.ogcc -pthread test.o ch4-PV.o -o test
tets.o:test.cgcc -c test.c
ch4-PV.o:ch4-PV.cgcc -c ch4-PV.c
.PHONY:cleanclean:rm -rf ch4-PV.orm -rf testrm -rf test.o
五、实现结果
首先进行make操作:

进行查看是否编译:

运行文件:

进行make clean操作:

到此一个简单的图书馆同步问题就实现了。
结语:Linux系统关于图书管理同步问题的分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~
相关文章:
Linux系统---图书管理中的同步问题
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、问题描述 (1)图书馆阅览室最多能够容纳N(N5)名学生,若有更多学生想…...
Vue学习笔记-activated和deactivated生命周期
作用 路由组件所独有的2个生命周期 activated生命周期函数用于在路由组件每次由消失到出现时所调用的函数deactivated生命周期函数用于路由组件每次由出现到消失时(无论是否缓存)所调用的函数 案例 定义一个NewsVue组件,要求:…...
102.套接字-Socket网络编程4(TCP通信流程)
目录 TCP编程流程 套接字函数 1.创建套接字 2.绑定地址 3.监听连接请求 4.接受连接 5. 连接到服务器 6. 发送数据 7. 接收数据 8.关闭套接字 服务器端通信流程 示例代码 客户端通信流程 代码示例 TCP编程流程 TCP是一个面向连接的,安全的,流…...
spring boot 2 升级到 spring boot 3 后文件上传失败
背景 项目需要,要求升级 spring boot 2.7 到 spring boot 3.2,升级过程中发现很多不兼容问题,下面说明文件上传失败的解决方案。 问题 spring boot 2 中不需要额外的配置,直接在 Controller 中配置 MultipartFile 接收页面传的…...
Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象
Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象。这可以通过使用 distinct() 和 filter() 方法来实现。 假设我们有两个 List,一个是 list1,另一个是 list2,我们想找出 list1 中存在但 list2…...
C语言还会存在多久
一、C语言的生命力 在当前的科技发展和就业市场需求下,可以肯定地说C语言并没有像一些新兴语言(如Python、JavaScript等)那样受到大量的关注。然而,并不意味着学习C语言的人会越来越少。 首先,C语言作为一种深受尊重…...
手持式安卓主板_PDA安卓板_智能手持终端方案
手持式安卓主板方案是一种智能终端设备,具备自动对焦和闪光灯功能,可以在昏暗的环境下快速扫描二维码并轻松采集数据。该方案还提供多渠道支付和数据采集功能,为用户提供了便捷的体验。 该方案的产品基于手持式安卓主板,并搭载了八…...
LeetCode103. Binary Tree Zigzag Level Order Traversal
文章目录 一、题目二、题解 一、题目 Given the root of a binary tree, return the zigzag level order traversal of its nodes’ values. (i.e., from left to right, then right to left for the next level and alternate between). Example 1: Input: root [3,9,20,n…...
PHP 判断给定两个时间是否在同一周,月,年
判断是否在同一周 date_default_timezone_set(PRC); //判断是否在同一周,原理:求出其中一个时间戳所在周的周一凌晨时间戳和周日24.00时间戳,如果另一个时间戳在这个范围内,则说明在同一周,否则不在同一周 function g…...
单机无锁线程安全队列-Disruptor
Disruptor 1、基本介绍 说到队列,除了常见的mq中间件,java中也自带线程安全的BlockingQueue,但是BlockingQueue通过在入队和出队时加锁的方式避免并发操作,性能上会大打折扣。 而Disruptor是一个线程安全、低延迟、吞吐量高的队…...
好工具知多少:国内外最常用的SCADA软件
随着现代SCADA系统的发展,工业自动化取得了巨大的飞跃。如今,监控和数据采集(SCADA)系统已成为工业过程的重要组成部分。这些系统使操作员能够实时监控和控制复杂的系统。 SCADA系统正在广泛的行业中发挥着至关重要的作用&#x…...
SQL Server 2016(创建数据库)
1、实验环境。 某公司有一台已经安装了SQL Server 2016的服务器,现在需要新建数据库。 2、需求描述。 创建一个名为"db_class"的数据库,数据文件和日志文件初始大小设置为10MB,启用自动增长,数据库文件存放路径为C:\db…...
Vue学习计划--Vue2(一)简单了解vue
Vue2的终止支持时间为2023年12月31日。 在这个矛盾的时间点,还是决定先把vue2的笔记放出来,在Vue2完结后再把Vue3的笔记补上。这样呢,2和3都不落下,也算是来一个启承的作用吧。在工作中呢,旧的项目可以维护,…...
微信小程序生成二维码并保存到本地方法
微信小程序生成二维码请保存到本地方法 官方weapp-qrcode插件 github链接 功能完成样子 wxml <view class"qrcode"><canvas style"width: 275px; height: 275px;" canvas-idmyQrcode></canvas> </view> <view class" …...
shell_exec 和 exec区别
shell_exec 和 exec 都是用于在 PHP 中执行系统命令的函数,但它们之间有一些区别。 返回值类型:shell_exec 函数返回命令的输出结果作为字符串,而 exec 函数将输出结果存储在数组中。 输出结果:shell_exec 函数返回命令的完整输出…...
WPF创建进度条
使用wpf做一个原生的进度条,进度条上面有值,先看效果。 功能就是点击按钮,后台处理数据,前台显示处理数据的变化,当然还可以对进度条进行美化和关闭的操作,等待后台处理完毕数据,然后自动关闭。…...
全网最新最全面的Appium自动化:Appium常用操作之混合应用webview页面操作--待补充!
上下文操作: 在appium中,对于混合应用,需要进行WebView页面和原生应用的切换 常用的方法如下: 1、context(self) / current_context(self):返回当前会话的当前上下文,context可以理解为可进入的窗口。对于…...
基于OpenCV+YOLOv5实现车辆跟踪与计数(附源码)
导 读 本文主要介绍基于OpenCVYOLOv5实现车辆跟踪与计数的应用,并给出源码。 资源下载 基础代码和视频下载地址: https://github.com/freedomwebtech/win11vehiclecount main.py代码: import cv2import torchimport numpy as npfrom tr…...
05、pytest断言确定的异常
官方用例 # content of test_sysexit.py import pytestdef f():raise SystemExit(1)def test_mytest():with pytest.raises(SystemExit):f()解读与实操 标准python raise函数可产生异常。pytest.raises可以断言某个异常会发现。异常发生了,用例执行成功&#x…...
金蝶云星空单据编辑界面,不允许批量填充操作
文章目录 金蝶云星空单据编辑界面,不允许批量填充操作案例演示开发设计测试 金蝶云星空单据编辑界面,不允许批量填充操作 案例演示 售后单,明细信息单据体,物料编码字段禁止批量填充。 开发设计 编写表单插件,在Be…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
