操作系统读者写者问题代码实现

article/2025/9/30 9:57:34

 

问题分析:

读者优先:

  • 读者进程执行:
    1. 无其他读者写者, 直接执行
    2. 有写者等, 但其他读者在读, 直接读
    3. 有写者写, 等待
  • 写者进程执行:
    1. 无其他读写者, 直接执行
    2. 有其他读写者, 等待

写者优先:

  • 读者进程执行:
    1. 如果此时没有写者等待, 直接执行
    2. 如果有写者等待, 那么等待
  • 写者进程执行:
    1. 如果没有其他写者, 那么执行
    2. 如果有其他读写者, 那么等待

伪代码:

读者优先:

读者R:
Wait(rmutex);
rcount++;
if(rcount == 1)
Wait(wmutex);
Signal(rmutex);
Read_Action();
Wait(rmutex);
rcount--;
if(rcount == 0)
Signal(wmutex);
Signal(rmutex);写者W:
Wait(wmutex);
Write_Action();
Signal(wmutex);

写者优先:

int wcount=0,rcount=0;
semaphore w=1,r=1,x=1;读者R:
reader(){P(r);P(x);rcount++;if(rcount==1)P(w);V(x);V(r);//Read()P(x);rcount--;if(rcount==0)V(w);V(x);
}写者W:
writer(){P(x);wcount++;if(wcount==1)P(r);V(x);P(w);//Write()V(w);P(x);wcount--;if(wcount==0)V(r);V(x);
}

源码C++实现:

#include <iostream>
#include <string.h> 
#include <memory.h>
#include <windows.h> 
#include <conio.h>
#include <stdlib.h>
#include <fstream> 
#define MAX_THREAD_NUM 64 //最大线程数 
#define INTE_PER_SEC 1000 //每秒时钟中断的数目 
#define MAX_FILE_NUM 32 //最大文件数目数 
#define MAX_STR_LEN 32 //字符串的长度 
using namespace std;
int readcount = 0; //读者数目 
int writecount = 0; //写者数目 
CRITICAL_SECTION RP_Write; //临界资源 
CRITICAL_SECTION cs_Write;
CRITICAL_SECTION cs_Read;
struct ThreadInfo
{int serial; //线程序号 char entity; //线程类别(判断是读者还是写者线程) double delay; //线程延迟时间 double persist; //线程读写操作时间 
};
//读者优先<--->读者线程//
void RP_ReaderThread(void *p) //P:读者线程信息
{//互斥变量 HANDLE h_Mutex;h_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex_for_readcount");DWORD wait_for_mutex; //等待互斥变量所有权 DWORD m_delay; //延迟时间 DWORD m_persist; //读文件持续时间 int m_serial; //线程序号 // 从参数中获得信息 m_serial = ((ThreadInfo*)(p))->serial;m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);Sleep(m_delay); //延迟等待cout << "Reader thread " << m_serial << " sents the reading require !" << endl;//等待互斥信号,保证对 ReadCount 的访问,修改互斥 wait_for_mutex = WaitForSingleObject(h_Mutex, -1);//读者数目增加 readcount++;if (readcount == 1){//第一个读者,等待资源 EnterCriticalSection(&RP_Write);}ReleaseMutex(h_Mutex); //释放互斥信//读文件 cout << "Reader thread " << m_serial << " begins to read file !" << endl;Sleep(m_persist);//退出线程 cout << "Reader thread " << m_serial << " finished reading file !" << endl;//等待互斥信号,保证对 ReadCount 的访问,修改互斥 wait_for_mutex = WaitForSingleObject(h_Mutex, -1);//读者数目减少 readcount--;if (readcount == 0){//如果所有的读者读完,唤醒写者 LeaveCriticalSection(&RP_Write);}ReleaseMutex(h_Mutex); //释放互斥信号 
}
//P:写者线程信息 
void RP_WriterThread(void *p)
{DWORD m_delay; //延迟时间 DWORD m_persist; //写文件持续时间 int m_serial; //线程序号 // 从参数中获得信息 m_serial = ((ThreadInfo*)(p))->serial;m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);Sleep(m_delay);cout << "Writer thread " << m_serial << " sents the writing require !" << endl;//等待资源 EnterCriticalSection(&RP_Write);//写文件 cout << "Writer thread " << m_serial << " begins to write file !" << endl;Sleep(m_persist);//退出线程cout << "Writer thread " << m_serial << " finished writing file !" << endl;//释放资源 LeaveCriticalSection(&RP_Write);
}
//读者优先处理函数
void ReaderPriority(const char *fileName)
{DWORD n_thread = 0; //线程数目 DWORD thread_ID; //线程 ID DWORD wait_for_all; //等待所有线程结束 //互斥对象 HANDLE h_Mutex;h_Mutex = CreateMutex(NULL, FALSE, "mutex_for_readcount");//线程对象的数组 HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];readcount = 0; //初始化 readcount InitializeCriticalSection(&RP_Write); //初始化临界区 ifstream inFile;inFile.open(fileName);if (!inFile){cout << "文件打开失败!" << endl;}cout << "读者优先:" << endl;while (inFile){//读入每一个读者,写者的信息 inFile >> thread_info[n_thread].serial;inFile >> thread_info[n_thread].entity;inFile >> thread_info[n_thread].delay;inFile >> thread_info[n_thread++].persist;inFile.get();}for (int i = 0; i < (int)(n_thread); i++){if (thread_info[i].entity == 'R'){//创建读者进程 h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(RP_ReaderThread),&thread_info[i], 0, &thread_ID);}else{//创建写线程 h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(RP_WriterThread), &thread_info[i], 0, &thread_ID);}}//等待所有的线程结束 wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);cout << "All reader and writer have finished operating !" << endl;
}//写者优先---读者线程 
//P:读者线程信息
void WP_ReaderThread(void *p)
{HANDLE print;print = CreateMutex(NULL, FALSE, LPCTSTR("mutex_for_print"));//互斥变量 HANDLE h_Mutex1;h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex1");HANDLE h_Mutex2;h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex2");DWORD wait_for_mutex1; //等待互斥变量所有权 DWORD wait_for_mutex2;DWORD m_delay; //延迟时间 DWORD m_persist; //读文件持续时间 int m_serial; //线程的序号 //从参数中得到信息 m_serial = ((ThreadInfo*)(p))->serial;m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);Sleep(m_delay); //延迟等待DWORD wait_to_print = WaitForSingleObject(print, -1);cout << "Reader thread " << m_serial << " sents the reading require !" << endl;ReleaseMutex(print);wait_for_mutex1 = WaitForSingleObject(h_Mutex1, -1);//读者进去临界区EnterCriticalSection(&cs_Read);//阻塞互斥对象 Mutex2,保证对 readCount 的访问和修改互斥 wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1);//修改读者的数目 readcount++;if (readcount == 1){// 如果是第 1 个读者,等待写者写完 EnterCriticalSection(&cs_Write);}ReleaseMutex(h_Mutex2);// 释放互斥信号 Mutex2 //让其他读者进去临界区 LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);//读文件 wait_to_print = WaitForSingleObject(print, -1);cout << "Reader thread " << m_serial << " begins to read file !" << endl;ReleaseMutex(print);Sleep(m_persist);//退出线程wait_to_print = WaitForSingleObject(print, -1);cout << "Reader thread " << m_serial << " finished reading file !" << endl;ReleaseMutex(print);//阻塞互斥对象 Mutex2,保证对 readcount 的访问,修改互斥wait_for_mutex1 = WaitForSingleObject(h_Mutex2, -1);readcount--;if (readcount == 0){//最后一个读者,唤醒写者 LeaveCriticalSection(&cs_Write);}ReleaseMutex(h_Mutex2); //释放互斥信号 
}/// 
//写者优先---写者线程 
//P:写者线程信息 
void WP_WriterThread(void *p)
{DWORD wait_for_mutex3; //互斥变量 DWORD m_delay; //延迟时间 DWORD m_persist; //读文件持续时间 int m_serial; //线程序号 HANDLE h_Mutex3;h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex3");//从参数中获得信息 m_serial = ((ThreadInfo*)(p))->serial;m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);Sleep(m_delay); //延迟等待 cout << "Writer thread " << m_serial << " sents the writing require !" << endl;wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);writecount++; //修改写者数目 if (writecount == 1){EnterCriticalSection(&cs_Read);}ReleaseMutex(h_Mutex3);EnterCriticalSection(&cs_Write);cout << "Writer thread " << m_serial << " begins to write file !" << endl;Sleep(m_persist);cout << "Writer thread " << m_serial << " finished writing file !" << endl;LeaveCriticalSection(&cs_Write);wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);writecount--;if (writecount == 0){LeaveCriticalSection(&cs_Read);}ReleaseMutex(h_Mutex3);
}/ 
//写者优先处理函数 
// fileName:文件名 
void WriterPriority(const char * fileName)
{DWORD n_thread = 0;DWORD thread_ID;DWORD wait_for_all;HANDLE h_Mutex1;h_Mutex1 = CreateMutex(NULL, FALSE, "mutex1");HANDLE h_Mutex2;h_Mutex2 = CreateMutex(NULL, FALSE, "mutex2");HANDLE h_Mutex3;h_Mutex3 = CreateMutex(NULL, FALSE, "mutex3");HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];readcount = 0;writecount = 0;InitializeCriticalSection(&cs_Write);InitializeCriticalSection(&cs_Read);ifstream inFile;inFile.open(fileName);cout << "Writer Priority:" << endl;while (inFile){inFile >> thread_info[n_thread].serial;inFile >> thread_info[n_thread].entity;inFile >> thread_info[n_thread].delay;inFile >> thread_info[n_thread++].persist;inFile.get();}for (int i = 0; i < (int)(n_thread); i++){if (thread_info[i].entity == 'R'){//创建读者进程h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(WP_ReaderThread), &thread_info[i], 0, &thread_ID);}else if (thread_info[i].entity == 'W'){//创建写线程 h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(WP_WriterThread), &thread_info[i], 0, &thread_ID);}}//等待所有的线程结束 wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);cout << "All reader and writer have finished operating !" << endl;
}
/ 
//主函数 
int main(void)
{system("color 3f"); //改变颜色const char * file = "test1.txt";char ch;while (1){cout << "--------------------------------读者与写者问题---------------------------------" << endl;cout << "*******************************************************************************" << endl;cout << "* 1、读者优先 *" << endl;cout << "* 2、写者优先 *" << endl;cout << "* 3、退出... *" << endl;cout << "*******************************************************************************" << endl;printf("请选择(1,2,3): ");do {ch = (char)getchar();} while (ch != '1'&&ch != '2'&&ch != '3');system("cls"); //执行清屏幕命令switch (ch){case '1':ReaderPriority(file);break;case '2':WriterPriority(file);break;case '3':return 0;}cout << endl << "按任意键继续..." << endl;getchar();system("cls");}return 0;
}

test1.txt内容:

1 R 3 5
2 W 4 5
3 R 5 2
4 R 6 5
5 W 5.1 3

结果:

 


http://chatgpt.dhexx.cn/article/oSYkwdqn.shtml

相关文章

读者写者问题详解 操作系统

2.16 读者写者问题 抽象解释 多个进程访问一个共享的数据区读者&#xff08;读进程&#xff09;只能读数据&#xff0c;写者&#xff08;写进程&#xff09;只能写数据适用于数据库、文件、内存、寄存器等数据区的访问模型如12306购票系统&#xff0c;由于用户量庞大和数据量…

同步机制—读者写者问题

【实验目的】 理解临界区和进程互斥的概念&#xff0c;掌握用信号量和PV操作实现进程互斥的方法。 【实验内容】 在windows或者linux环境下编写一个控制台应用程序&#xff0c;该程序运行时能创建N个线程&#xff0c;其中既有读者线程又有写者线程&#xff0c;它们按照事先设计…

操作系统——读者写者问题

一、问题描述 要求: 1、允许多个读者可以同时对文件执行读操作。 2、只允许一个写者往文件中写信息。 3、任一写者在完成写操作之前不允许其他读者或写者工作。 4、写者执行写操作前,应让已有的读者和写者全部退出。 二、问题分析 读者写者问题最核心的问题是如何处理…

【操作系统-进程】PV操作——读者写者问题

文章目录 读者写者问题万能模板万能模板 1——读进程优先万能模板 2——读写公平法万能模板 3——写进程优先 题目 1&#xff1a;南北过桥问题题目 2&#xff1a;录像厅问题题目 3&#xff1a;更衣问题 读者写者问题万能模板 读者写者问题&#xff0c;其本质就是连续多个同类进…

经典进程同步问题(三)——读者写者问题

目录 一、问题描述 二、解题思路 2.1 读者优先算法 2.2 写者优先算法 2.3 读写公平 三、源码实现 3.1 读者优先 3.2 写者优先 3.3 读写平等 一、问题描述 一个数据问价或记录可以被多个进程共享&#xff0c;我们把只读该文件的进程称为“读者进程”&#xff0c;其他进…

2. 堆与栈的区别

2. 堆与栈的区别 在理解这两个概念时&#xff0c;需要放到具体的场景下&#xff0c;因为不同场景下&#xff0c;堆与栈代表不同的含义。一般情况下&#xff0c;有两层含义&#xff1a; &#xff08;1&#xff09;程序内存布局场景下&#xff0c;堆与栈表示的是两种内存管理方式…

栈与堆的区别(内存分配与数据结构)

参考自https://blog.csdn.net/K346K346/article/details/80849966/ 堆&#xff08;Heap&#xff09;与栈&#xff08;Stack&#xff09;包含两层含义&#xff1a; 程序内存布局场景下的内存管理方式数据结构中的两种常见的数据结构 1. 程序内存分配中的堆与栈 1.1 栈介绍 …

C语言里栈和堆的区别整理

这里说的是C语言程序内存分配中的堆和栈。下面先谈谈C语言的内存管理&#xff1a; 可执行程序在存储时&#xff08;没有调到内存&#xff09;分为代码区&#xff08;text&#xff09;、数据区&#xff08;data&#xff09;和未初始化数据区&#xff08;bss&#xff09;3个部分。…

看懂堆与栈的区别与联系

<div class"simditor-body clearfix" style"height: auto; overflow: inherit;"><h2> <strong>  堆和栈概要</strong></h2>在计算机领域&#xff0c;堆栈是一个不容忽视的概念&#xff0c;堆栈是两种数据结构。堆栈都是一…

C语言:栈和堆的区别

c语言五大内存分区 栈区&#xff08;stack&#xff09;:存放函数形参和局部变量&#xff08;auto类型&#xff09;&#xff0c;由编译器自动分配和释放 堆区&#xff08;heap&#xff09;:该区由程序员申请后使用&#xff0c;需要手动释放否则会造成内存泄漏。如果程序员没有手…

什么是栈(Stack)?什么是堆(Heap)?栈和堆的区别是什么?

原参考地址&#xff1a;https://zhidao.baidu.com/question/36918441.html 栈&#xff1a;由操作系统自动分配释放 &#xff0c;存放函数的参数值&#xff0c;局部变量du的值等。其操作方式类似于数据结构中的栈&#xff1b; 堆&#xff1a; 一般由程序员分配释放&#xff0c…

堆和栈的概念和区别

在说堆和栈之前&#xff0c;我们先说一下JVM&#xff08;虚拟机&#xff09;内存的划分&#xff1a; Java程序在运行时都要开辟空间&#xff0c;任何软件在运行时都要在内存中开辟空间&#xff0c;Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域&#x…

堆与栈的区别详细总结

1、堆与栈的区别详细总结_Fighting的博客-CSDN博客_堆和栈的区别 2、堆和栈的区别 - 江雨牧 - 博客园 3、堆和栈的区别_内外皆秀的博客-CSDN博客_堆和栈的区别 4、一文读懂堆与栈的区别_恋喵大鲤鱼的博客-CSDN博客_堆和栈的区别 一般情况下&#xff0c;如果有人把堆栈合起来…

栈和堆的区别

栈和堆的区别 前面已经介绍过&#xff0c;栈是由编译器在需要时分配的&#xff0c;不需要时自动清除的变量存储区。里面的变量通常是局部变量、函数参数等。堆是由malloc()函数分配的内存块&#xff0c;内存释放由程序员手动控制&#xff0c;在C语言为free函数完成。栈和堆的主…

Struts常见面试题

Struts分为Struts1和Struts2&#xff0c;默认情况下指的是Struts2&#xff0c;Struts1除非特别说明。 1、Struts2 中的 # 和 % 分别是做什么的&#xff1f; &#xff08;1&#xff09;使用#获取 context 里面的数据 <s:iterator value “list” var”user”> <s:p…

关于Struts2的笔试题(一)

一. struts2框架中struts.xml配置文件,package标签的属性有那几个?各有什么功能? 1.name属性 作用:定义一个包的名称&#xff0c;它必须唯一。 2.namespace属性 作用:主要是与action标签的name属性联合使用来确定一个action 的访问路径 3.extends属性 作用:指定继承自哪个…

Struts2详述一(struts2基础及2个核心)

临近大学毕业了&#xff0c;在毕业之前做点大学学到的知识和总结。如有哪些方面存在错误还望大神见谅。 首先&#xff0c;这里想从SSH这三大框架说起。首选从最简单的Struts2说起。这一篇我将讲述struts2一些基础及2个核心&#xff08;Action和result&#xff09;,下篇我们将着…

【面试】【Struts2常见问题总结】【02】

【常见面试问题总结目录>>>】 031 struts2如何对指定的方法进行验证&#xff1f; 1.validate()方法会校验action中所有与execute方法签名相同的方法&#xff1b;   2.要校验指定的方法通过重写validateXxx()方法实现&#xff0c; validateXxx()只会校验action中方法…

【面试】【Struts2常见问题总结】【01】

【常见面试问题总结目录>>>】 001 请简述struts1的工作流程和机制&#xff1a; Struts的工作流程:   在web应用启动时就会加载初始化ActionServlet,ActionServlet从   struts-config.xml文件中读取配置信息,把它们存放到各种配置对象   当ActionServlet接收到…

一道Struts面试题

题目是这样的 有两张表 一张为新闻类别表 有&#xff12;个字段&#xff1a; nid(pk) sort 有一张新闻内容表 有三个字段 cid(pk) nid(fk) title content 要求通过下拉列表框的方法选择新闻类别然后显示该类别的新闻标题&#xff08;在当前…