问题描述:

所谓读者写着问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书。为实现读写同步,需要使用信号量机制。信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者则是这一机制的一个经典范例。

对利用信号量来解决读者—写者问题的描述如下:

1)写-写互斥,即不能有两个写者同时进行写操作;
2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写;
3)读读允许,即可以有2个以上的读者同时读。

课设要求:

本次课程设计中,在处理读者写者等待队列的请求时,用到了两种唤醒进程算法:读者优先唤醒算法和写者优先唤醒算法。

读优先:当一个读者与若干写者同时处于等待队列中时,并且此时并无写操作进行时,读者优先进行读。
写优先:当一个读者与若干写者同时处于等待队列中时,并且此时并无写操作进行时,写者优先进行写。

主要数据结构:

typedef struct
{
int id;
char name[256];
int operateTime;
int flag;//1为读者,2为写者
}runQueue;//进行中队列结构;

typedef struct
{
int id;
char name[256];
int operatetime;
int flag;//1为读等待,2为写等待
}wait;//等待队列结构;

个人思路:

创建两个队列,一个队列用于存储进行中的进程;一个队列用于存储等待中的进程。当创建读者进程或写者进程时,查看当前进行中队列是否已满,若已满则进入等待者队列。当一个进程结束时,查看其是否占用队列最后一位,若是则等待中队列进程可进入进行中队列。在单个进程对队列操作时,对队列使用p操作,结束后使用v操作释放。

环境:

编译器:codeblocks20.03
c语言:c11
操作系统:windows10

代码:

主函数以及各定义

#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <string.h>typedef struct
{int id;
char name[256];
int operateTime;
int flag;//1为读者,2为写者
}runQueue;//进行中队列结构;typedef struct
{int id;
char name[256];
int operatetime;
int flag;//1为读等待,2为写等待
}wait;//等待队列结构;int id = 0;//全局变量id
int waitqLen=0,runqLen=0;     //全局变量三个队列的长度
int waitqNLen=0,runqNLen=0;  //全局变量三个队列目前的长度
int nowThread = 0;//目前线程数
int operating1 = 0,operating2 = 0;//正在对队列操作的进程
wait waitQueue[1000]={};   //等待者队列
runQueue runningQueue[1000]={};//进行中队列void showQueue();//展示目前队列情况
void creatReader();//创建读者
void creatWriter();//创建写者
void readerThread();//读者线程
void writerThread();//写者线程
void WaitToRun();//等待队列进入进行中队列(读者优先)
void WaitToRunWFirst();//等待队列进入进行中队列(写者优先)
void runWaitToRun();//进入队列线程开启
void AreaderThread();//单个读者线程
void AwriterThread();//单个写者线程int main()
{printf("请输入等待队列长度:");scanf("%d",&waitqLen);printf("请输入进行中队列长度:");scanf("%d",&runqLen);int Choice = 0;while(1){Choice=0;printf("1.查看当前队列情况\n");printf("2.创建读者\n");printf("3.创建写者\n");printf("4.退出\n");printf("请输入操作项:");scanf("%d",&Choice);switch(Choice){case 1:showQueue();break;case 2:creatReader();break;case 3:creatWriter();break;case 4:return 0;break;}}}

展示目前队列

void showQueue()
{printf("\n/****---------------------****/\n");printf("当前进程数:%d\n\n",nowThread);printf("等待者队列:\n");for(int i=1;i<=waitqNLen;i++){printf("/**\n等待者id:%d\n",waitQueue[i].id);printf("等待者名:%s\n",waitQueue[i].name);if(waitQueue[i].flag==1)printf("等待者类型:读者\n");elseprintf("等待者类型:写者\n");printf("等待者操作时间:%ds\n**/\n",waitQueue[i].operatetime);}printf("---------------------\n");printf("进行中队列:\n");for(int i=1;i<=runqNLen;i++){if(runningQueue[i].flag==1){printf("/**\n读者id:%d\n",runningQueue[i].id);printf("读者名:%s\n**/\n",runningQueue[i].name);}else{printf("/**\n写者id:%d\n",runningQueue[i].id);printf("写者名:%s\n**/\n",runningQueue[i].name);}}printf("\n/****---------------------****/\n\n");
}

创建读者、写者

void creatReader()
{if(runqNLen == runqLen || runningQueue[0].flag==2){printf("当前进行中队列已满,进入等待队列。\n");if(waitqNLen == waitqLen){printf("等待队列已满,入队失败!\n");}else{id++;waitqNLen++;waitQueue[waitqNLen].id=id;printf("请输入读者名:");scanf("%s",waitQueue[waitqNLen].name);waitQueue[waitqNLen].flag=1;printf("请输入读时间:");scanf("%d",&waitQueue[waitqNLen].operatetime);printf("已进入等待队列。\n");return 0;}return 0;}else{id++;int readtime=0;runqNLen++;runningQueue[runqNLen].id=id;printf("请输入读者名:");scanf("%s",runningQueue[runqNLen].name);runningQueue[runqNLen].flag = 1;printf("请输入阅读时间(单位:秒):");scanf("%d",&readtime);runningQueue[runqNLen].operateTime=readtime;printf("开启读者线程成功,读者id:%d,读者名称%s\n",id,runningQueue[runqNLen].name);_beginthread(readerThread,0,NULL);nowThread++;}}void creatWriter()
{if(runqNLen != 0){printf("当前进行中队列已满,进入等待队列。\n");if(waitqNLen == waitqLen){printf("等待队列已满,入队失败!\n");}else{id++;waitqNLen++;waitQueue[waitqNLen].id=id;printf("请输入读者名:");scanf("%s",waitQueue[waitqNLen].name);waitQueue[waitqNLen].flag=2;printf("请输入读时间:");scanf("%d",&waitQueue[waitqNLen].operatetime);printf("已进入等待队列。\n");return 0;}return 0;}else{id++;int readtime=0;runqNLen++;runningQueue[runqNLen].id=id;printf("请输入写者名:");scanf("%s",runningQueue[runqNLen].name);runningQueue[runqNLen].flag = 2;printf("请输入写作时间(单位:秒):");scanf("%d",&readtime);runningQueue[runqNLen].operateTime=readtime;printf("开启写者线程成功,写者id:%d,写者名称%s\n",id,runningQueue[runqNLen].name);_beginthread(writerThread,0,NULL);nowThread++;}}

等待队列进入/读者优先/


void WaitToRun()
{if(waitqNLen==0)return 0;else{while(1){if(operating1==0)break;Sleep(200);}operating1=1;for(int i = 1;i<=waitqNLen;i++){if(waitQueue[i].flag == 1){while(1){if(operating2==0)break;Sleep(200);}operating2=1;runqNLen++;runningQueue[runqNLen].flag=waitQueue[i].flag;runningQueue[runqNLen].id=waitQueue[i].id;strcpy(runningQueue[runqNLen].name,waitQueue[i].name);runningQueue[runqNLen].operateTime=waitQueue[i].operatetime;printf("开启读者线程成功,读者id:%d,读者名称%s\n",runningQueue[runqNLen].id,runningQueue[runqNLen].name);_beginthread(AreaderThread,0,NULL);operating2=0;for(int j = i;j<=waitqNLen;j++){waitQueue[j]=waitQueue[j+1];}waitqNLen--;operating1=0;return 0;}operating1=0;if(i==waitqNLen&&runqNLen==0){while(1){if(operating1==0)break;Sleep(200);}operating1=1;for(i=1;i<=waitqNLen;i++){if(waitQueue[i].flag == 2){while(1){if(operating2==0)break;Sleep(200);}operating2=1;runqNLen++;runningQueue[runqNLen].flag=waitQueue[i].flag;runningQueue[runqNLen].id=waitQueue[i].id;strcpy(runningQueue[runqNLen].name,waitQueue[i].name);runningQueue[runqNLen].operateTime=waitQueue[i].operatetime;printf("开启写者线程成功,写者id:%d,写者名称%s\n",runningQueue[runqNLen].id,runningQueue[runqNLen].name);_beginthread(AwriterThread,0,NULL);operating2=0;for(int j = i;j<=waitqNLen;j++){waitQueue[j]=waitQueue[j+1];}waitqNLen--;operating1=0;return 0;}}operating1=0;return 0;}}}}

等待队列进入/写者优先/


/*写者优先*/
void WaitToRunWFirst()
{if (waitqNLen == 0)return 0;else{while (1){if (operating1 == 0)break;Sleep(200);}operating1 = 1;for (int i = 1; i <= waitqNLen; i++){if (waitQueue[i].flag == 2){while (1){if (operating2 == 0)break;Sleep(200);}operating2 = 1;runqNLen++;runningQueue[runqNLen].flag = waitQueue[i].flag;runningQueue[runqNLen].id = waitQueue[i].id;strcpy(runningQueue[runqNLen].name, waitQueue[i].name);runningQueue[runqNLen].operateTime = waitQueue[i].operatetime;printf("开启读者线程成功,读者id:%d,读者名称%s\n", runningQueue[runqNLen].id, runningQueue[runqNLen].name);_beginthread(AreaderThread, 0, NULL);operating2 = 0;for (int j = i; j <= waitqNLen; j++){waitQueue[j] = waitQueue[j + 1];}waitqNLen--;operating1 = 0;return 0;}operating1 = 0;if (i == waitqNLen){while (1){if (operating1 == 0)break;Sleep(200);}operating1 = 1;for (i = 1; i <= waitqNLen; i++){if (waitQueue[i].flag == 1){while (1){if (operating2 == 0)break;Sleep(200);}operating2 = 1;runqNLen++;runningQueue[runqNLen].flag = waitQueue[i].flag;runningQueue[runqNLen].id = waitQueue[i].id;strcpy(runningQueue[runqNLen].name, waitQueue[i].name);runningQueue[runqNLen].operateTime = waitQueue[i].operatetime;printf("开启写者线程成功,写者id:%d,写者名称%s\n", runningQueue[runqNLen].id, runningQueue[runqNLen].name);_beginthread(AwriterThread, 0, NULL);operating2 = 0;for (int j = i; j <= waitqNLen; j++){waitQueue[j] = waitQueue[j + 1];}waitqNLen--;operating1 = 0;return 0;}}operating1 = 0;return 0;}}}}

进程的内操作

void AreaderThread()
{nowThread++;int threadID=runningQueue[runqNLen].id;Sleep(1000*runningQueue[runqNLen].operateTime);while(1)//当有线程在操作队列时等待其操作结束才能开始操作{if(operating2==0)break;Sleep(200);}operating2=1;for(int i=1;i<=runqNLen;i++){if(runningQueue[i].id==threadID){printf("\n读者线程结束,读者id:%d,读者名称:%s\n",runningQueue[i].id,runningQueue[i].name);for(int j = i;j<=runqNLen;j++){runningQueue[j]=runningQueue[j+1];}runqNLen--;break;}}operating2=0;WaitToRun();nowThread--;_endthread();}void AwriterThread()//单个写者线程
{nowThread++;int threadID=runningQueue[runqNLen].id;Sleep(1000*runningQueue[runqNLen].operateTime);while(1)//当有线程在操作队列时等待其操作结束才能开始操作{if(operating2==0)break;Sleep(200);}operating2=1;for(int i=1;i<=runqNLen;i++){if(runningQueue[i].id==threadID){printf("\n写者线程结束,写者id:%d,写者名称:%s\n",runningQueue[i].id,runningQueue[i].name);for(int j = i;j<=runqNLen;j++){runningQueue[j]=runningQueue[j+1];}runqNLen--;break;}}operating2=0;nowThread--;WaitToRun();_endthread();
}void writerThread()
{int threadID=id;Sleep(1000*runningQueue[runqNLen].operateTime);while(1)//当有线程在操作队列时等待其操作结束才能开始操作{if(operating2==0)break;Sleep(200);}operating2=1;for(int i=1;i<=runqNLen;i++){if(runningQueue[i].id==threadID){printf("\n写者线程结束,写者id:%d,写者名称:%s\n",runningQueue[i].id,runningQueue[i].name);for(int j = i;j<=runqNLen;j++){runningQueue[j]=runningQueue[j+1];}runqNLen--;break;}}operating2=0;nowThread--;WaitToRun();_endthread();}void readerThread()
{int threadID=id;Sleep(1000*runningQueue[runqNLen].operateTime);while(1){if(operating2==0)break;Sleep(200);}operating2=1;for(int i=1;i<=runqNLen;i++){if(runningQueue[i].id==threadID){printf("\n读者线程结束,读者id:%d,读者名称:%s\n",runningQueue[i].id,runningQueue[i].name);for(int j = i;j<=runqNLen;j++){runningQueue[j]=runningQueue[j+1];}runqNLen--;break;}}operating2=0;nowThread--;WaitToRun();_endthread();}

操作系统课程设计----读者-写者 问题(c语言)相关推荐

  1. 操作系统课程设计报告总结(下)

    操作系统课程设计报告总结(下) 实验六 银行家算法的模拟与实现 实验目的 总体设计 背景知识 基本原理 模块介绍 详细设计 关键代码及分析 实验结果与分析 小结与心得体会 银行家算法源码 实验七 磁盘 ...

  2. 华科计算机课程设计,华中科大操作系统课程设计报告(附源码).doc

    华中科技大学计算机学院 操作系统课程设计报告 班级: 学号: 姓名:彭博 时间:2010年3月 设计内容一:熟悉和理解Linux编程环境 编写一个C程序,实现文件拷贝功能. 2)编写一个C程序,使用下 ...

  3. python操作系统课程设计_操作系统课程设计.pdf

    计算机科学与通信工程学院 操作系统课程设计报告 题目:linux系统下实现PV 操作 班级: 软件工程1401 姓名: 吴帅帅 学号: 3140608020 指导老师: 牛德姣 2016 年12 月2 ...

  4. 计算机操作实践的课程描述,计算机操作系统课程设计实践报告-Read.DOC

    计算机操作系统课程设计实践报告-Read <计算机操作系统>课程设计实践报告 班级:计科31班第二组 组长:吕岭 小组成员:邢自成.叶林.张鹰 [问题描述] 模拟二级以上的多级文件目录管理 ...

  5. 操作系统课程设计pintos project1实验摘记

    前言: 本篇意在记录本学期结束的操作系统课程设计pintos project1实验报告和实现过程.整个实验参考了多篇文章也查阅了一些代码,其中部分内容或与其他文章相同,还请见谅.同时,也为了测试CSD ...

  6. HDU操作系统课程设计实验三

    HDU操作系统课程设计实验三 一.设计目的 二.内容要求 三.实验内容 信号量的使用 1.实现一个模拟的shell,基本功能加find.grep命令 2.实现一个管道通信程序,基本功能加有名管道通信 ...

  7. GeekOS操作系统课程设计 project0

    GeekOS操作系统课程设计 project0 项目设计0 一.项目设计目的 二.项目设计要求 三.项目0的实现主要由以下步骤完成: 四.步骤 1.编写项目0的/src/geekos/main.c ( ...

  8. 操作系统课程设计报告2021-2022——pintos

    操作系统课程设计报告 2021-2022 目录 操作系统课程设计报告 2021-2022 第一章 实验项目介绍 环境配置 ( 一 ). Ubuntu 服务器搭建 图形界面搭建 ( 二 ). Pinto ...

  9. 操作系统作业调度算法c语言,操作系统课程设计报告电梯调度算法c语言实现.doc...

    操作系统课程设计报告电梯调度算法c语言实现 操作系统课程设计报告电梯调度算法c语言实现 :调度 算法 电梯 课程设计 操作系统 操作系统课程设计报告 模拟操作系统课程设计 写一个简单的操作系统 篇一: ...

最新文章

  1. 配置windows失败,不能进入系统
  2. 划分微型计算机的标志是,划分微型计算机的标志为
  3. 解决GitHub中头像显示异常、设置不了头像、README图片无法显示等问题
  4. 面试突击 | Redis 如何从海量数据中查询出某一个 Key?视频版
  5. Win11系统如何设置任务栏新消息提醒
  6. 设计包含min函数的栈,O(1)空间实现方法
  7. 思科五个高危漏洞 CDPwn 影响数千万台企业设备
  8. Crossoft Minesweeper Hexagon for Mac
  9. 中标普华下LibFetion1.3,i386,rpm包
  10. 电脑计算机丢失msvcp140.dll,电脑缺少msvcp140.dll怎么办
  11. python opencv图像笔记
  12. 递推练习之费解的开关
  13. Java项目:ssm+jsp实现手机WAP版外卖订餐系统
  14. 简单linux命令之备份文件
  15. arm linux源更新,[Linux] - Manjaro ARM 系统配置(更新镜像源,安装 Docker 和 Dotnet Core)...
  16. python实例属性
  17. systemUI之statusBar
  18. 单边指数信号的傅立叶matlab,实验四连续信号的傅立叶变换
  19. 解决Macbook在win7系统下不能识别USB设备,完全没反应
  20. java查询学号数据库_数据库SQL查询语句练习题 PDF 下载

热门文章

  1. Android 9-patch 九图的制作与使用
  2. 【091】肖邦《降B小调第一夜曲》
  3. [Android]ProgressBar进度条
  4. 最新推荐 | 清华NLP图神经网络GNN论文分门别类,16大应用200+篇论文
  5. 新手自主创业需要注意哪些误区
  6. linux基础教程课后答案,Linux教材课后习题答案.pdf
  7. 自动获取指定路径文件夹,删除文件夹及子文件
  8. Python分类检测问题的常用指标 - TPR TNR TPR f1-score
  9. 红米3 android 版本,四型号五版本分不清?红米3各大版本详细解读
  10. 计算机主板 开机什么也不显示,电脑开机无显示,不是主板也不是CPU问题,而是它坏了...