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

在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;
}

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

  1. 操作系统之多线程编程—读者优先/写者优先详解

    操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...

  2. 操作系统 | PV操作七大经典问题 生产者消费者 读者写者 哲学家进餐 理发师理发睡觉 和尚打水 吸烟者 吃水果

    一.生产者消费者问题 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案 ...

  3. 爬取淘宝女郎的照片-写给初步入门爬虫的读者

    爬取淘宝女郎照片-写给初步入门爬虫的读者 要爬取的照片示例: python2.7爬虫代码如下: #coding=utf-8 import urllib2mmurl = "https://mm ...

  4. 【学术写作】写综述小窍门,教你轻松写综述

    点击上方,选择星标或置顶,每天给你送干货! 阅读大概需要10分钟 跟随小博主,每天进步一丢丢 转载:毕业论文写作攻略 前言 综述是指就某一时间内,作者针对某一专题,对大量原始研究论文中的数据.资料和主 ...

  5. python识别手写数字字体_基于tensorflow框架对手写字体MNIST数据集的识别

    本文我们利用python语言,通过tensorflow框架对手写字体MNIST数据库进行识别. 学习每一门语言都有一个"Hello World"程序,而对数字手写体数据库MNIST ...

  6. 进程P1、P2、P3共享一个表格F,P1对F只读不写,P2对F只写不读,P3对F先读后写。进程可同时读F,但有进程写时,其他进程不能读和写。

    进程P1.P2.P3共享一个表格F,P1对F只读不写,P2对F只写不读,P3对F先读后写.进程可同时读F,但有进程写时,其他进程不能读和写.要求:(1)正常运行时不能产生死锁.(2)F的并发度要高. ...

  7. python写界面进度条程序_Python中如何写控制台进度条的整理

    进度条和一般的print区别在哪里呢? 答案就是print会输出一个\n,也就是换行符,这样光标移动到了下一行行首,接着输出,之前已经通过stdout输出的东西依旧保留,而且保证我们在下面看到最新的输 ...

  8. 别人写好的爬虫怎么运行_怎么写好楷书?

    谢谢邀请! 对于提主的"如何写出漂亮的楷书"这个问题,发表一下自己的看法,供参考之. 楷书,字之楷模也! 楷书本身就是中规中矩.漂漂亮亮的书体,想写出漂亮的楷书,最好的办法是选择一 ...

  9. “如何写好科技论文之我见”结束语-如何写好科技论文之我见(十)

    "如何写好科技论文之我见"结束语-如何写好科技论文之我见(十) 闵应骅 终于在国庆60周年前夕完成了"如何写好科技论文之我见"系列博文.根据自己平时跟学生常讲的 ...

  10. html中写css代码,开发DIV CSS时 先写CSS代码还是先写HTML代码

    相信良多LOVE用DIV+CSS技术启示重构网页的爱好者友好,在起源学习DIV+CSS的时分都邑想一个标题,想晓得DIV+CSS妙手或有教育者在开发制作html页面的时刻,下场是先写html照样先写c ...

最新文章

  1. 自定义注解妙用,一行代码搞定用户操作日志记录,你学会了吗?
  2. 大数据征信需把控 数据源的“量”与“度”
  3. Wordpress上传图片的存储逻辑
  4. 小学生图片_中秋节手抄报,小学生中秋节手抄报图片大全
  5. java计算器算法描述_基于Java的计算器算法(源代码)
  6. 使用泛型, 写一个为任意类型的动态数组添加元素的方法
  7. 2018年全国多校算法寒假训练营练习比赛(第一场)F. 大吉大利,今晚吃鸡——跑毒篇(模拟)
  8. python学习之-文件和对象
  9. 《Android MVPArms 使用butterknife遇到的坑》
  10. 通过js获取本机的IP地址
  11. 2018深圳杯数学建模A题--人才吸引力评价模型研究
  12. 浩辰ICAD电气软件IDq2003i.rar
  13. html如何在表单里加虚线,大佬,表格下方的虚线怎么添加?
  14. 程度性数据python分析_python数据分析实战之AQI分析
  15. 十年,AMD“三剑合一”再出击
  16. 2.6 Photoshop操作步骤的撤消和重做 [Ps教程]
  17. ora-600[kcbz_check_objd_typ]错误处理
  18. EndNote20 快速入门
  19. 大数据BI工具Tableau学习【第二期】]带你领略Tableau 的页面风采
  20. 一种基于熔丝修调的修调方案设计

热门文章

  1. 使用html记笔记,如何用前端的方式记笔记
  2. 可调直流恒流源工作时温度过高解决方法
  3. DIY ROV系列(二)ROV架构介绍
  4. 洛谷 P1595 信封问题 1
  5. 不用table标签实现表格
  6. zip压缩文件明文攻击以及相关问题
  7. 低秩表示的学习--Latent Low-Rank Representation(LatLLR)
  8. HDLBits学习(五)Circuits--Sequential Logic(时序逻辑)-Latched and Fli-Flops
  9. 三维CAD核心技术及发展趋势
  10. python可以做工业视觉_(Python)从零开始,简单快速学机器仿人视觉Opencv—运用四:图像损痕修复...