操作系统 读者写者问题的实现(C++ 读者优先、写者优先)

article/2025/9/30 7:59:55

通过信号量机制和相应的系统调用,用于线程的互斥和同步,实现读者写者问题。利用信号量机制,实现读者写者问题。

在windows 10环境下,创建一个控制台进程,此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按照设定进行读写操作。用信号量机制分别实现读者优先和写者优先的读者写者问题。
读者和写者问题的读写操作限制(包括读者优先和写者优先):
写写互斥:即不能有两个写者同时进行写操作。
读写互斥:即不能同时有一个线程在读,而另一个线程在写。
读读允许:即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态才能开始读操作。

读者优先:
如果没有写者正在操作,则读者并不需要等待,用一个整型变量readercount表示正在读的进程数目。由于只要有一个Reader进程在读,便不允许Writer进程去写,于是仅当readercount=0时,说明尚无读者进程在读,Reader进程才需要执行wait(book)操作。若该操作成功了,Reader进程便可去读,相应地,做readercount+1操作。同理,仅当Reader进程在执行了readercount减一操作后其值为0时,才须执行signal(book)操作,以便让Writer进程写操作。,每个读者开始读之前都要修改readercount,为了互斥的实现对readercount 的修改,需要一个互斥对象rc_mutex来实现互斥。
为实现Reader与Writer进程间在读或在写的互斥而设置一个互斥的信号量book,表示对资源的访问。当写者发出写的请求时,必须先得到允许。通过这种方法,可以实现读写互斥,当readcount=0时,(即第一个读者的到来时,),读者线程也必须申请。
当读者拥有所有权,写者都阻塞在信号量对象book上。当写者拥有所有权时,第一个判断完readcount==0 后,其余的读者由于等待对readcount的判断,阻塞在rc_mutex上。

写者优先:
写者优先和读者优先有相同之处,不同的地方在:一旦有一个写者到来时,应该尽快让写者进行写,如果有一个写者在等待,则新到的读者操作不能读操作,为此添加一个整型变量writercount,记录写者的数目,当writercount=0时才可以释放读者进行读操作。
为了实现对全局变量writercount的互斥访问,设置了一个互斥信号量wc_mutex,同时,读者线程要对全局变量readercount实现操作上的互斥,必须有一个互斥对象命名为。
为了实现写者优先,设置一个临界区对象read,当有写者在写或等待时,读者必须阻塞在临界区对象read上。同样,有读者读时,写者必须等待。于是,必须有一个互斥对象book来实现这个互斥。
写者的操作应该优先于读者,则信号量一直被占用着,直到没有写者的时候才会释放,即当writerCount等于1的时候,申请信号量book,其余的写者无需再次申请,但是写者是不能同时进行写操作的,则需要设置一个信号量wrt来保证每次只有一个写者进行写操作,当写者的数量writeCount等于0的时候,则证明此时没有没有读者了,释放信号量book。当readCount为1的时候,为阻止写者进行写操作,申请信号量wrt,则写者就无法进行写操作了。信号量mutex的主要用处就是避免写者同时与多个读者进行竞争,读者中信号量book比mutex先释放,则一旦有写者,写者可马上获得资源。

实现效果图:

读者写者测试文本
在这里插入图片描述
读者优先:
在这里插入图片描述
写者优先:
在这里插入图片描述

最后给出源码:

#include<iostream>
#include<string>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h> 
#include <fstream>
#include <io.h>
#include <string.h>
#include<algorithm>
#include<Windows.h> //多线程编程
#include<process.h>
using namespace std;#define READER 'R'                   //读者
#define WRITER 'W'                   //写者
#define INTE_PER_SEC 1000            //每秒时钟中断的数目
#define MAX_THREAD_NUM 64            //最大线程数目//变量声明初始化
int readercount = 0;//记录等待的读者数目
int writercount = 0;//记录等待的写者数目HANDLE rc_mutex;//因为读者数量而添加的互斥信号量,用于读者优先HANDLE rc2_mutex;//因为读者数量而添加的互斥信号量,用于写者优先
HANDLE wc_mutex;//因为写者数量而添加的互斥信号量
HANDLE book;//互斥访问信号量
HANDLE wrt;//保证每次只有一个写者进行写操作,当写者的数量writercount等于0的时候,则证明此时没有没有读者了,释放信号量book
HANDLE mutex;//避免写者同时与多个读者进行竞争,读者中信号量RWMutex比mutex3先释放,则一旦有写者,写者可马上获得资源struct thread_info {int id;		      //线程序号char entity;      //线程类别(判断是读者线程还是写者线程)double delay;		 //线程延迟时间double lastTime;	 //线程读写操作时间
};
/*****************/
//读者优先
//进程管理-读者线程
void rp_threadReader(void *p)
{DWORD m_delay;                   //延迟时间DWORD m_persist;                 //读文件持续时间int m_serial;                    //线程序号//从参数中获得信息m_serial = ((thread_info*)(p))->id;m_delay = (DWORD)(((thread_info*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((thread_info*)(p))->lastTime *INTE_PER_SEC);Sleep(m_delay);                  //延迟等待printf("读者进程%d申请读文件.\n", m_serial);//cout << "读者进程"<< m_serial<<"申请读文件." << endl;WaitForSingleObject(rc_mutex, -1);//对readercount互斥访问if (readercount == 0)WaitForSingleObject(book, -1);//第一位读者申请书readercount++;ReleaseSemaphore(rc_mutex, 1, NULL);//释放互斥信号量rc_mutexprintf("读者进程%d开始读文件.\n", m_serial);Sleep(m_persist);printf("读者进程%d完成读文件.\n", m_serial);WaitForSingleObject(rc_mutex, -1);//修改readercountreadercount--;//读者读完if (readercount == 0)ReleaseSemaphore(book, 1, NULL);//释放书籍,写者可写ReleaseSemaphore(rc_mutex, 1, NULL);//释放互斥信号量rc_mutex
}
/*****************/
//读者优先
//进程管理-写者线程
void rp_threadWriter(void *p)
{DWORD m_delay;                   //延迟时间DWORD m_persist;                 //读文件持续时间int m_serial;                    //线程序号//从参数中获得信息m_serial = ((thread_info*)(p))->id;m_delay = (DWORD)(((thread_info*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((thread_info*)(p))->lastTime *INTE_PER_SEC);Sleep(m_delay);                  //延迟等待printf("写者进程%d申请写文件.\n", m_serial);WaitForSingleObject(book, INFINITE);//申请资源/*write is performed*/printf("写者进程%d开始读文件.\n", m_serial);Sleep(m_persist);printf("写者进程%d完成读文件.\n", m_serial);ReleaseSemaphore(book, 1, NULL);//释放资源
}
//读者优先
void ReaderPriority(char *file)
{DWORD n_thread = 0;           //线程数目DWORD thread_ID;            //线程IDDWORD wait_for_all;         //等待所有线程结束//创建信号量rc_mutex = CreateSemaphore(NULL, 1, 1, "mutex_for_readcount");//读者对count修改互斥信号量,初值为1,最大为1book = CreateSemaphore(NULL, 1, 1, NULL);//书籍互斥访问信号量,初值为1,最大值为1HANDLE h_Thread[MAX_THREAD_NUM];//线程句柄,线程对象的数组thread_info thread_info[MAX_THREAD_NUM];int id = 0;readercount = 0;               //初始化readcountifstream inFile;inFile.open(file);cout << "读者优先:" << endl;while (inFile){//读入每一个读者,写者的信息inFile >> thread_info[n_thread].id;inFile >> thread_info[n_thread].entity;inFile >> thread_info[n_thread].delay;inFile >> thread_info[n_thread++].lastTime;inFile.get();}for (int i = 0; i<(int)(n_thread); i++){if (thread_info[i].entity == READER || thread_info[i].entity == 'r'){//创建读者进程h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(rp_threadReader), &thread_info[i], 0, &thread_ID);}else{//创建写线程h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(rp_threadWriter), &thread_info[i], 0, &thread_ID);}}//等待子线程结束//关闭句柄wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);cout << endl;cout << "所有读者写者已经完成操作!!" << endl;for(int i = 0; i<(int)(n_thread); i++)CloseHandle(h_Thread[i]);CloseHandle(rc_mutex);CloseHandle(book);
}
/*****************/
//写者优先
//进程管理-读者线程
void wp_threadReader(void *p) {DWORD m_delay;                   //延迟时间DWORD m_persist;                 //读文件持续时间int m_serial;                    //线程序号//从参数中获得信息m_serial = ((thread_info*)(p))->id;m_delay = (DWORD)(((thread_info*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((thread_info*)(p))->lastTime *INTE_PER_SEC);Sleep(m_delay);                  //延迟等待printf("读者进程%d申请读文件.\n", m_serial);WaitForSingleObject(mutex, -1);WaitForSingleObject(book, -1);WaitForSingleObject(rc2_mutex, -1);//对readercount互斥访问if (readercount == 0)WaitForSingleObject(wrt, -1);//第一位读者申请书,同时防止写者进行写操作readercount++;ReleaseSemaphore(rc2_mutex, 1, NULL);//释放互斥信号量rc_mutexReleaseSemaphore(book, 1, NULL);//释放互斥信号量bookReleaseSemaphore(mutex, 1, NULL);//释放互斥信号量mutex/* reading is performed */printf("读者进程%d开始读文件.\n", m_serial);Sleep(m_persist);printf("读者进程%d完成读文件.\n", m_serial);WaitForSingleObject(rc2_mutex, -1);//修改readercountreadercount--;//读者读完if (readercount == 0)ReleaseSemaphore(wrt, 1, NULL);//释放资源,写者可写ReleaseSemaphore(rc2_mutex, 1, NULL);//释放互斥信号量rc_mutex
}
/*****************/
//写者优先
//进程管理-写者线程
void wp_threadWriter(void *p) {DWORD m_delay;                   //延迟时间DWORD m_persist;                 //读文件持续时间int m_serial;                    //线程序号//从参数中获得信息m_serial = ((thread_info*)(p))->id;m_delay = (DWORD)(((thread_info*)(p))->delay *INTE_PER_SEC);m_persist = (DWORD)(((thread_info*)(p))->lastTime *INTE_PER_SEC);Sleep(m_delay);                  //延迟等待printf("写者进程%d申请写文件.\n", m_serial);WaitForSingleObject(wc_mutex, -1);//对writercount互斥访问if (writercount == 0)WaitForSingleObject(book, -1);//第一位写者申请资源writercount++;ReleaseSemaphore(wc_mutex, 1, NULL);//释放资源WaitForSingleObject(wrt, -1);/*write is performed*/printf("写者进程%d开始写文件.\n", m_serial);Sleep(m_persist);printf("写者进程%d完成写文件.\n", m_serial);ReleaseSemaphore(wrt, 1, NULL);//释放资源WaitForSingleObject(wc_mutex, -1);//对writercount互斥访问writercount--;if (writercount == 0)ReleaseSemaphore(book, 1, NULL);//释放资源ReleaseSemaphore(wc_mutex, 1, NULL);//释放资源
}
//写者优先
void WriterPriority(char *file) {DWORD n_thread = 0;           //线程数目DWORD thread_ID;            //线程IDDWORD wait_for_all;         //等待所有线程结束//创建信号量rc2_mutex = CreateSemaphore(NULL, 1, 1, "mutex_for_readercount");//读者对count修改互斥信号量,初值为1,最大为1wc_mutex = CreateSemaphore(NULL, 1, 1, "mutex_for_writercount");//写者对count修改互斥信号量,初值为1,最大为1wrt = CreateSemaphore(NULL, 1, 1, NULL);//mutex = CreateSemaphore(NULL, 1, 1, NULL);//book = CreateSemaphore(NULL, 1, 1, NULL);//书籍互斥访问信号量,初值为1,最大值为1HANDLE h_Thread[MAX_THREAD_NUM];//线程句柄,线程对象的数组thread_info thread_info[MAX_THREAD_NUM];int id = 0;readercount = 0;               //初始化readcountwritercount = 0;ifstream inFile;inFile.open(file);cout << "写者优先:" << endl;while (inFile){//读入每一个读者,写者的信息inFile >> thread_info[n_thread].id;inFile >> thread_info[n_thread].entity;inFile >> thread_info[n_thread].delay;inFile >> thread_info[n_thread++].lastTime;inFile.get();}for (int i = 0; i<(int)(n_thread); i++){if (thread_info[i].entity == READER || thread_info[i].entity == 'r'){//创建读者进程h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(wp_threadReader), &thread_info[i], 0, &thread_ID);}else{//创建写线程h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(wp_threadWriter), &thread_info[i], 0, &thread_ID);}}//等待子线程结束//关闭句柄wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);cout << endl;cout << "所有读者写者已经完成操作!!" << endl;for (int i = 0; i<(int)(n_thread); i++)CloseHandle(h_Thread[i]);CloseHandle(wc_mutex);CloseHandle(rc2_mutex);CloseHandle(book);
}
//主函数
int main()
{char choice;cout << "    欢迎进入读者写者模拟程序    " << endl;while (true){//打印提示信息cout << "     请输入你的选择       " << endl;cout << "     1、读者优先" << endl;cout << "     2、写者优先" << endl;cout << "     3、退出程序" << endl;cout << endl;//如果输入信息不正确,继续输入do {choice = (char)_getch();} while (choice != '1'&&choice != '2'&&choice != '3');system("cls");//选择1,读者优先if (choice == '1')//ReaderPriority("thread.txt");ReaderPriority(const_cast<char *>("thread.txt"));//选择2,写者优先else if (choice == '2')WriterPriority(const_cast<char *>("thread.txt"));//选择3,退出elsereturn 0;//结束printf("\nPress Any Key to Coutinue");_getch();system("cls");}return 0;
}

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

相关文章

信号量机制实现读者写者问题(思路剖析+Java代码实现+验证)

写在前面&#xff1a; Java中&#xff1a; 我们用这样的代码新建一个信号量&#xff1a;Semaphore mutex new Semaphore(1);P操作(wait)的代码为&#xff1a;mutex.acquire();V操作(signal)的代码为&#xff1a;mutex.release(); 本文章的内容&#xff1a; 读者写者问题&#…

Java实现读者写者问题--读者优先

作者&#xff1a;凌杰林 简介 临界资源&#xff1a;同一时间只能由一个进程访问的资源 临界区&#xff1a;访问临界资源的代码段 读者写者问题&#xff1a;存在一个多个进程共享的数据区&#xff08;临界资源&#xff09;&#xff0c;该数据区可以是一个文件或者一块内存空间…

操作系统实验:读者写者问题

一&#xff0e;实验目的&#xff1a; 通过实现读者写者问题理解进程及信号量的概念 二&#xff0e;实验要求&#xff1a; 创建一个控制台进程&#xff0c;此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求进行读写操作。用信号量机制分…

信号量机制——读者-写者问题

信号量机制——读者-写者问题 问题描述 一个共享数据区&#xff0c;有若干个进程负责对其进行读入工作&#xff0c;若干个进程负责对其进行写入工作。 允许多个进程同时读数据互斥读数据若有进程写数据&#xff0c;不允许读者读数据 对照生活中的购票系统&#xff1a; 一个…

操作系统:读者写者问题

操作系统&#xff1a;读者写者问题 问题&#xff1a;一、读者-写者问题: 读者优先二、读者-写者问题&#xff1a;写进程优先 三、读者写者问题的应用---独木桥问题类型1.一次只能过一辆车类型2.一次能过多辆车 四、总结附代码&#xff1a;//读者优先//写者优先//公平竞争 教材原…

四、操作系统——读者写者问题(详解)

一、问题描述&#xff1a; 二、需要满足的条件&#xff1a; 写进程与写进程之间必须互斥的写入数据&#xff08;因为如果两个写进程同时对共享数据中的区域A中的数据进行写操作的话&#xff0c;会导致数据错误覆盖的问题&#xff09;写进程与读进程之间必须互斥的访问共享数据…

锁机制:读者写者问题 Linux C

最近碰到一些锁机制的问题&#xff0c;想起大三的时候做过的一个小课设&#xff0c;记录复习一下。 问题描述&#xff1a; 一个数据文件可以被多个进程共享&#xff0c;其中&#xff0c;有些进程要求读&#xff08;reader进程&#xff09;&#xff0c;而另一些进程要求对数据…

写优先的读者写者问题(Java实现)

该题系吉林大学19级软件学院操作系统课设题之一 先输入初始时的写者读者情况&#xff0c;优先级顺序做了随机处理 代码如下 GUI&#xff1a; import javax.swing.*; import javax.swing.border.Border; import javax.swing.text.BadLocationException; import javax.swing.tex…

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

问题分析&#xff1a; 读者优先: 读者进程执行: 无其他读者写者, 直接执行有写者等, 但其他读者在读, 直接读有写者写, 等待写者进程执行: 无其他读写者, 直接执行有其他读写者, 等待 写者优先: 读者进程执行: 如果此时没有写者等待, 直接执行如果有写者等待, 那么等待写者…

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

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…