读者 写者问题C 源代码
读者-写者问题(Reader-Writer Problem)
学号:课程设计题目用多线程同步方法解决读者-写者问题(Reader-Writer Problem)学院计算机科学与技术学院专业软件工程班级姓名指导教师2010 年 6 月日目录目录 (1)课程设计任务书 (1)正文 (2)1.设计目的与要求 (2)1.1设计目的 (2)1.2设计要求 (2)2.设计思想及系统平台 (2)2.1设计思想 (2)2.2系统平台及使用语言 (3)3.详细算法描述 (3)4.源程序清单 (6)5.运行结果与运行情况 (9)6.调试过程 (11)7.总结 (12)本科生课程设计成绩评定表 (13)课程设计任务书学生姓名:专业班级:指导教师:工作单位:计算机科学与技术学院题目: 用多线程同步方法解决读者-写者问题(Reader-Writer Problem)初始条件:1.操作系统:Linux2.程序设计语言:C语言3.设有20个连续的存储单元,写入/读出的数据项按增序设定为1-20这20个字符。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.技术要求:1)为每个读者/写者产生一个线程,设计正确的同步算法2)每个读者/写者对该存储区进行操作后,即时显示该存储区的全部内容、当前指针位置和读者/写者线程的自定义标识符。
3)读者应有3个以上,写者应有有两个以上。
4)多个读者/写者之间须共享对存储区进行操作的函数代码。
2.设计说明书内容要求:1)设计题目与要求2)总的设计思想及系统平台、语言、工具等。
3)数据结构与模块说明(功能与流程图)4)给出用户名、源程序名、目标程序名和源程序及其运行结果。
(要注明存储各个程序及其运行结果的主机IP地址和目录。
)5)运行结果与运行情况(提示: (1)连续存储区可用数组实现。
(2)编译命令可用:cc -lpthread -o 目标文件名源文件名(3)多线程编程方法参见附件。
)3. 调试报告:1) 调试记录2)自我评析和总结上机时间安排:18周一~ 五08:0 -12:00指导教师签名:年月日系主任(或责任教师)签名:年月日正文1.设计目的与要求1.1设计目的通过研究Linux的线程机制和信号量实现读者写者问题(Reader-Writer Problem )的并发控制。
操作系统读者写者问题 源代码
在linux环境下运行!#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#include<errno.h>#include<stdlib.h>#include<stdio.h>#include<unistd.h>union semun{int val;struct semid_ds *buf;unsigned short *array;struct seminfo *_buf;};int *readcount;static int shmid,semid,s;int main(){key_t semkey,shmkey,skey;union semun arg;if((semkey=ftok(".",0x16))==-1) printf("error1\n") ;if((skey=ftok(".",0x36))==-1) printf("error3\n");if((shmid=shmget(IPC_PRIVATE,1024,0600|IPC_CREAT))==-1) printf("error4\n"); if((shmat(shmid,NULL,0))==-1) printf("error!\n");readcount=(int *)shmat(shmid,NULL,0);semid=semget(semkey,1,0600|IPC_CREAT);s=semget(skey,1,0600|IPC_CREAT);arg.val=1;semctl(semid,0,SETVAL,arg);semctl(shmid,0,SETVAL,arg);semctl(s,0,SETVAL,arg);int initsem(int key){return(semget(key,1,0600|IPC_CREAT|IPC_EXCL));}int P(int semidd,int semnun){struct sembuf sops={semnun,-1,SEM_UNDO};return(semop(semidd,&sops,1));}int V(int semidd,int semnun){struct sembuf sops={semnun,+1,SEM_UNDO};return(semop(semidd,&sops,1));}void writer(int k){while(k>0){P(s,0);P(semid,0);if(*readcount==0) P(shmid,0);(*readcount)++;V(semid,0);V(s,0);printf("XIE jing c\n");P(semid,0);(*readcount)--;;if((*readcount)==0) V(shmid,0); V(semid,0);k--;}}void reader(int j){while(j>0){P(s,0);P(shmid,0);printf("DU jing c\n");V(shmid,0);V(s,0);j--;}}writer(5);reader(6);return 0;}。
读者——写者 代码
Sleep(m_persist);
//退出线程
printf("Reader thread %d finished reading file.\n",m_serial);
//等待互斥信号,保证对ReadCount的访问,修改互斥
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);
}
ReleaseMutex(h_Mutex); //释放互斥信号
}
//////////////////////////////////////////////////////////////
//P:写者线程信息
};
///////////////////////////////////////////////////////////////////////////
// 读者优先---读者线程
//P:读者线程信息
void RP_ReaderThread(void *p)
ifstream inFile;
inFile.open (file);
printf("Reader Priority:\n\n");
while(inFile)
{
//读入每一个读者,写者的信息
char entity; //线程类别(判断是读者还是写者线程)
double delay; //线程延迟时间
double persist; //线程读写操作时间
inFile>>thread_info[n_thread].serial;
inFile>>thread_info[n_thread].entity;
C图书管理系统源代码
C图书管理系统源代码Newly compiled on November 23, 2020图书管理系统系统功能:1.借书:根据借书人提出的图书编号(id)查询该图书,如果该图书现存量(store)不为0,则提示输入借阅者的学号(num),为借书人办理借书手续,提示用户该书已被借出。
2.归书:根据借书人的学号查询该读者的信息,若有该读者,则提示输入所借书籍的编号(id),为该读者办理还书手续,提示该书已还。
3.书籍管理:弹出书籍管理界面,输入所要执行操作的号码:(1)增加书籍:弹出注册新书的窗口,按照提示输入所增加书籍的信息,最后,提示用户该书已被注册。
(2)删除书籍:弹出删除书籍的窗口,输入所要删除书籍的编号(id),输出该书的信息,确认是否删除该书,1为删除,0为放弃。
(3)修改书籍:弹出修改书籍的窗口,输入所要修改书籍的编号(id),输出该书的信息,确认是否修改该书,1为修改,0为放弃。
之后按照提示重新输入书籍的信息。
4.读者管理:弹出读者管理界面,输入所要执行操作的号码:(1)增加读者:弹出注册读者的窗口,按照提示输入所增加读者的信息,最后,提示用户该读者已被注册。
(2)删除书籍:弹出删除读者的窗口,输入所要删除读者的学号(num),输出该读者的信息,确认是否删除该读者,1为删除,0为放弃。
(3)修改书籍:弹出修改读者的窗口,输入所要修改读者的学号(num),输出该读者的信息,确认是否修改该读者,1为修改,0为放弃。
之后按照提示重新输入读者的信息。
5.搜索:此搜索包括两方面的搜索,书籍搜索以及读者搜索,弹出搜索的窗口,按照提示输入所要搜索的内容,1为书籍搜索,2为读者搜索:(1)搜索书籍:弹出搜索书籍的窗口,按照提示输入所要搜索的方式,包括按<1>书名搜索,<2>书号搜索,<3>作者搜索,<4>出版社搜索,<5>出版时间搜索;根据所选方式输入相应的内容,若是该书籍存在,则输出该书籍的信息,否则,返回主界面。
OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)
OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)⼀. 引⼦最近想⾃⼰写个简单的 WEB SERVER ,为了先练练⼿,熟悉下在LINUX系统使⽤基本的进程、线程、互斥等,就拿以前学过的 OS 问题开开⼑啦。
记得当年学读者写者问题,尤其是写者优先的时候,那是真⼼纠结啊。
刚才还觉得理解了,过⼀会⼉⼜糊涂了。
现在重新再看,还是容易纠结。
没办法,⽤得少。
我把读者优先和写者优先都实现了⼀下。
选择性重看了⼩部分《unix⾼程》使⽤了多线程+互斥量实现。
⼆. 互斥量与信号量互斥量如其名,同⼀时间只能被⼀个线程占有,实现线程间对某种数据结构的互斥访问。
试图对⼀个已经加锁的互斥量加锁,会导致线程阻塞。
允许多个线程对同⼀个互斥量加锁。
当对互斥量解锁时,阻塞在该互斥量上的线程会被唤醒,它们竞争对该互斥量加锁,加锁成功的线程将停⽌阻塞,剩余的加锁失败于是继续阻塞。
注意到,谁将竞争成功是⽆法预料的,这⼀点就类似于弱信号量。
(强信号量把阻塞在信号量上的进程按时间排队,先进先出)互斥量区别于信号量的地⽅在于,互斥量只有两种状态,锁定和⾮锁定。
它不像信号量那样可以赋值,甚⾄可以是负值。
共性⽅⾯,我所体会到的就⼀句话,都是⽤来实现互斥的。
⾄于其它区别或联系,⽤不上,不作研究。
三. 读者优先只要有⼀个读者正在读,那么后续的读者都能⽴即读,不管有多少写者在等待。
可能导致写者饥饿。
1. 读者1) 写者写时,不可读2) 有别的读者正在读,可读2. 写者1) 有读者正在读,不可写2) 有写者正在写,不可写3) ⽆读者正在读,⽆写者正在写,可写四. 写者优先当新的写者希望写时,不允许该写者后续的读者访问数据区,但必须保证之前的读者读完。
1. 读者特点1) 有写者正在写或者等待写,须等到没有写者才能读2) 没有写者,可以读2. 写者特点1) 写者与写者互斥。
当其它写者正在写时,其它写者不能写。
2) 写者与读者互斥。
之前只有读者在读,当写者出现时,必须等到之前的读者都读完才能写。
在linux下实现读者写者问题源代码
在linux下实现读者写者问题源代码读者写者问题是计算机科学中的一个经典同步问题,用于描述多个读者和写者对共享资源的访问。
在这个问题中,多个读者可以同时读取共享资源,但是写者在写入共享资源时必须独占访问。
在Linux下,我们可以使用线程和互斥锁来实现读者写者问题。
下面是一个简单的源代码示例:```c#include <stdio.h>#include <stdlib.h>#include <pthread.h>#define READERS_COUNT 5#define WRITERS_COUNT 2pthread_mutex_t mutex;pthread_cond_t cond_reader, cond_writer;int readers = 0;int writers = 0;void *reader(void *arg) {int id = *(int *)arg;while (1) {pthread_mutex_lock(&mutex);while (writers > 0) {pthread_cond_wait(&cond_reader, &mutex); }readers++;pthread_mutex_unlock(&mutex);// 读取共享资源printf("Reader %d is reading\n", id);pthread_mutex_lock(&mutex);readers--;if (readers == 0) {pthread_cond_signal(&cond_writer);}pthread_mutex_unlock(&mutex);}pthread_exit(NULL);}void *writer(void *arg) {int id = *(int *)arg;while (1) {pthread_mutex_lock(&mutex);while (readers > 0 || writers > 0) {pthread_cond_wait(&cond_writer, &mutex); }writers++;pthread_mutex_unlock(&mutex);// 写入共享资源printf("Writer %d is writing\n", id);pthread_mutex_lock(&mutex);writers--;pthread_cond_signal(&cond_writer);pthread_cond_broadcast(&cond_reader);pthread_mutex_unlock(&mutex);}pthread_exit(NULL);}int main() {pthread_t readers[READERS_COUNT];pthread_t writers[WRITERS_COUNT];int reader_ids[READERS_COUNT];int writer_ids[WRITERS_COUNT];pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond_reader, NULL);pthread_cond_init(&cond_writer, NULL);// 创建读者线程for (int i = 0; i < READERS_COUNT; i++) {reader_ids[i] = i + 1;pthread_create(&readers[i], NULL, reader, &reader_ids[i]); }// 创建写者线程for (int i = 0; i < WRITERS_COUNT; i++) {writer_ids[i] = i + 1;pthread_create(&writers[i], NULL, writer, &writer_ids[i]); }// 等待线程结束for (int i = 0; i < READERS_COUNT; i++) {pthread_join(readers[i], NULL);}for (int i = 0; i < WRITERS_COUNT; i++) {pthread_join(writers[i], NULL);}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond_reader);pthread_cond_destroy(&cond_writer);return 0;}```在这个源代码中,我们使用了互斥锁(`pthread_mutex_t`)和条件变量(`pthread_cond_t`)来实现读者写者问题的同步。
读者写者
char thread_name[3]; //线程名
unsigned int require_moment; //请求操作时刻
unsigned int persist_time; //操作持续时间
CRITICAL_SECTION CS_DATA; //用于保护文件的临界区变量
HANDLE h_mutex_read_count=CreateMutex(NULL,FALSE,"mutex_read_count");
//读者计数器互斥体
HANDLE h_mutex_write_count=CreateMutex(NULL,FALSE,"mutex_write_count");
}
WaitForMultipleObjects(MAX_THREAD,h_thread,TRUE,-1); //等待所有线程结束
printf("\n");
}
//无优先时的读者线程
void FIFO_reader_thread(void *data){
char thread_name[3];
}TEST_INFO;
TEST_INFO test_data[MAX_THREAD]={ //测试数据表
{"r1",0,15},
{"r2",1, 15},
{"w1",3,3},
{"r3",4, 2},
//写者计数器互斥体
HANDLE h_mutex_reader_wait=CreateMutex(NULL,FALSE,"mutex_reader_wait");
基于C++的读者与写者问题read—writeproblem的实现(一)
基于C++的读者与写者问题read—writeproblem的实现(一)基于C++的读者与写者问题的实现 11.设计题目与要求 12.总的设计思想及系统平台、语言、工具等 12.1设计思想 12.2系统平台,语言,工具 43.数据结构与模块说明(功能与流程图) 43.1功能实现 43.2流程图 64.源程序 74.1.ReaderAndWriter.CPP //具体的实现 74.2.thread.dat//辅助的文件,但是必不可以少 155.运行结果与运行情况 156.调试记录 177.自我评析和总结 18基于C++的读者与写者问题read—writeproblem的实现1.设计题目与要求读者写者问题(read—writeproblem)是一个经典的并发程序设计问题。
有两组并发进程:读者和写者,共享一个问题F,要求:(1)允许多个读者可同时对之执行读*作;(2)只允许一个写者往文件中写信息;(3)任一写者在完成写*作之前不允许其他读者或者写者工作;(4)写者执行写*作前,应让已有的写者和读者全部退出。
2.总的设计思想及系统平台、语言、工具等2.1设计思想根据题目要求,首先分析了以下4种可能发生的情况:第1种情况:读者的优先权比写者高,而且,不用调配。
所有读者的优先权都比写者的优先权高,而且,不用调配。
一个读者需要等待的唯一情况是,一个写者已经占用了文件。
一个写者可以取得文件的条件是,没有一个读者处在等待状态或正在读文件。
允许读者们结盟,以便能长期占用文件,而禁止写者的写。
第2种情况:在一个读者已经占有了文件的时候,全体读者的优先权才比写者高。
在没有任何一个读者在读文件时,读者的优先权和写者的优先权相同。
相反,如果有一个读者正在读文件,则其余的各读者都可以读文件,而不管有多少写者处在等待状态。
所有读者都有权结盟,以便垄断文件。
第3种情况:写者的优先权比读者的优先权高。
在一个写者提出要访问文件时,就必须使其尽可能的得到文件,而且不用调配。
读者写者问题C源代码
读者——写者问题C++程序(原创作品)演示效果图:程序完整代码:#include <windows.h>#include <iostream.h>#include <fstream.h>#include <string.h>#include<string>#include<stdlib.h>//包含清屏头文件//全局变量int empty=1;//信号量int wrIn=1;//信号量int max;int temp[30];int *wait,*next;int count=0;//记录已经完成操作的线程数int waitSemapore;int type;//类型记录int writc=1;int readc=1;void reader()/////////////////////////////////////////////////////读者函数开始{empty--;//P操作改变信号量cout<<"读者获得资源"<<"(";SYSTEMTIME sys;GetLocalTime(&sys);//输出系统时间cout<<"系统时间:"<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<":"<<sys.wMilliseconds<<")"<<e ndl;cout<<endl<<"*"<<"读者正在进行读操作..."<<endl;//empty++;//信号量count++;}/////////////////////////////////////////////////////////读者函数结尾void writer()//////////////////////////////////////////////////写者函数开始{empty--;//P操作改变信号量wrIn--;//P操作改变信号量cout << " 写者"<<writc<<"获得资源" <<"(";SYSTEMTIME sys;GetLocalTime(&sys);//输出系统时间cout<<"系统时间:"<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<":"<<sys.wMilliseconds<<")"<<endl;cout<<"请输入线程要写入的内容,以/结尾"<<endl;char ch='a';ofstream outfile("f.txt",ios::out|ios::app);if(!outfile){cerr<<"open file error!"<<endl;abort();}while(ch!='/'){ cin>>ch;outfile<<ch;}cout<<endl<<"*" <<"写者"<<writc<<"正在进行写操作.." << endl;outfile.close();count++;//wrIn++;//V操作改变信号量//empty++;//V操作改变信号量}//////////////////////////////////////////////////////////////写者函数结尾void codeIn()/////////////////////////////////////////////////////////////////输入界面{int ru;cout<<"请输入你要创建多少个线程:"<<endl;cin>>max;for(int i=0;i<max;i++){cout<<"你所要创建的第"<<i+1<<"个线程类型为:1.读者 2.写者"<<endl; cin>>ru;///////////////if(ru==1||ru==2)temp[i]=ru;elsecout<<"输入有误!请重新输入"<<endl;/////////////判断错误if(i==max-1)//录入最后一个线程类型操作{//system("cls");//清屏HANDLE hOut;hOut = GetStdHandle(STD_OUTPUT_HANDLE); //设置输出字体颜色red SetConsoleTextAttribute(hOut,FOREGROUND_RED |FOREGROUND_INTENSITY);cout<<endl<<"输入完毕!"<<endl;hOut = GetStdHandle(STD_OUTPUT_HANDLE); //设置输出字体背景SetConsoleTextAttribute(hOut,BACKGROUND_GREEN |BACKGROUND_INTENSITY); for(int j=0;j<max;j++)//////////////////输出录入结果{cout<<"线程"<<j+1<<"为:";if(temp[j]==1)cout<<"读者"<<endl;else cout<<"写者"<<endl;}///////////////////////////////输出录入结果cout<<"下面将进行动态演示:"<<endl<<endl;system("pause");cout<<endl;}//录入最后一个线程类型操作}//录入界面结束}}/////////////////////////////////////////////////////////codeIn()int main()/////////////////////////////////////////////////主函数{codeIn();//录入界面wait=&temp[0];while(wait<&temp[max]&&count<max){waitSemapore=1;next=wait;while(*next==1||*next==2)//线程调用算法{if(*next==1)//reader{if(empty==1||(empty==0&&wrIn==1&&*wait!=2))//体现写者优先{reader();//调用读者函数type=1;}else{cout<<"["<<"读者此时正在等待资源"<<"]"<<endl;//Sleep(5000);////////////////////////////////////////////////////////////////////////////////////////////sleep() if(waitSemapore==1){wait=next;//////////this reader is waiting,locate it.waitSemapore--;}}}else//writer{if(empty==1){writer();//调用写者函数type=2;}else{cout<<"["<<"写者此时正在等待资源"<<"]"<<endl;//Sleep(5000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()if(waitSemapore==1)///////////this writer is waiting,find it's location.{wait=next;waitSemapore--;}}}//writer is endnext++;}//1while()if(type==1){cout<<"~"<<"读者"<<readc<<"读完毕,释放资源"<<endl;readc++;empty++;//读者用的,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()cout<<endl;}elseif(type==2){cout<<"~"<<"写者"<<writc<<"写完毕,释放资源" << endl;writc++;wrIn++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处empty++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()cout<<endl;}}//2while()return 0;}/////////////////////////////////////////////////////主函数结束。
读者写者问题源代码
}Pcb,*link;
int s1,s2; //信号量
link p1;//生产者进程
link c1;//消费者进程
char str[MAX]; //输入的字符串
char buffer[BUF]; //缓冲池
int len; //输入长度
int sp=0; //string的指针
link p;
int num1=0;
int num2=0;
if(s==1){//生产进程
strcpy(p1->state,"Block");//改变状态
strcpy(p1->reason,"S1");//说明原因
p=b_s1;
while(p){
num1++;
p=p->next;//p的值为NULL,表示队尾
}
void processor(){ //模拟处理器指令执行
int i;
if(strcmp(ready->name,"Producer")==0) //当前进程为生产者
switch(pc)
{
case 0://produce
printf("\t*生产者生产了字符%c\n",str[sp]);
rec_p[rp1]=str[sp];//添加到生产记录
while(q->next)//插入就绪队列
q=q->next;
q->next=p;
p->next=NULL;
printf("\t* c1消费进程唤醒了!\n");
}
}
读者写者问题C源代码
读者——写者问题C++程序(原创作品)演示效果图:程序完整代码:#include <>#include <>#include <>#include <>#include<string>#include<>."<<endl; " << endl;();者 2.写者"<<endl;cin>>ru; waitSemapore--;}}}else {wait=next;waitSemapore--;}}}//writer is endnext++;}//1while()if(type==1){cout<<"~"<<"读者"<<readc<<"读完毕,释放资源"<<endl;readc++;empty++;//读者用的,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()}elseif(type==2){cout<<"~"<<"写者"<<writc<<"写完毕,释放资源" << endl;writc++;wrIn++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处empty++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()cout<<endl;}}//2while()return 0;}/////////////////////////////////////////////////////主函数结束。
读者-写者问题代码解释
读者-写者问题有同学反映“读者-写者问题”的代码比较难理解。
主要是因为Windows提供了一种互斥机制称为“Critical Section”,中文翻译为“临界区”,这个名字具有迷惑性,因为,它容易与我们课本上讲的“临界区”的概念混淆。
课本上临界区指“对临界资源进行访问的代码”;而这种称为“Critical Section”互斥机制,并不是这个意思,而是访问临界区之前的一种加锁机制,与Mutex 信号量的作用类似,只是“Critical Section”互斥机制只能在同一进程内部各个线程间使用,而Mutex互斥机制是可以跨进程使用的。
为帮助大家更容易理解读者-写者的代码,下面的代码用Mutex互斥机制替换了“Critical Section”互斥机制,并添加了部分注释,并用蓝色标注,其原理都是一样的。
#include "windows.h"#include "process.h"#include <conio.h>#include <stdlib.h>#include <fstream.h>#include <io.h>#include <string.h>#include <stdio.h>#define READER 'R' // 读者#define WRITER 'W' // 写者#define INTE_PER_SEC 1000 // 每秒时钟中断数目#define MAX_THREAD_NUM 64 // 最大线程数目#define MAX_FILE_NUM 32 // 最大数据文件数目#define MAX_STR_LEN 32 // 字符串长度volatile int readcount = 0; // 读者数目HANDLE RP_Write;struct ThreadInfo // 定义线程数据结构{int serial; // 线程序号char entity; // 线程类别(判断是读者线程还是写者线程)double delay; // 线程延迟double persist; // 线程读写操作持续时间};/////////////////////////////////////////////////////////////////////////// 读者优先——读者线程/// p:读者线程信息unsigned int __stdcall RP_ReaderThread(void *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) ; //延迟等待printf("Reader thread %d sents the reading require......\n",m_serial);//等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1);// 读者数目增加readcount++;if(readcount ==1){//这是第一个读者,第二个读者到来时,readcount为2,if的条件不满足,不会进入if语句内部执行//这是第一个读者,如果此刻没有写者正在写,则RP_Write信号量状态为可用(未占用),那它就必须先占用(锁定)RP_Write信号量,这就实现了读-写互斥//如果此刻有写者正在写,则RP_Write信号量被写者占用(锁定),读者想对RP_Write加锁就会阻塞在此,等待RP_Write信号量释放后,才能继续运行WaitForSingleObject(RP_Write, INFINITE);}ReleaseMutex(h_Mutex) ; //释放互斥信号// 读文件printf("Reader thread %d begins to read file.\n",m_serial);Sleep(m_persist) ;// 退出线程printf("Reader thread %d finished reading file.\n",m_serial);//等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1) ;//读者数目减少readcount-- ;if(readcount == 0){//如果所有读者读完,则释放RP_Write信号量;此刻若有写者正在等待(处于阻塞状态),将(自动)唤醒写者ReleaseMutex(RP_Write);}ReleaseMutex(h_Mutex) ; //释放互斥信号return 0;}////////////////////////////////////////////////////////////////////////// 读者优先——写者线程// p:写者线程信息unsigned int __stdcall 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); //延迟等待printf("Writer thread %d sents the writing require.\n",m_serial);// 写者在进行写数据之前,必须确定没有其它写者正在写,也没有其它读者在读,// 通过RP_Write互斥量实现,若有其它写者正在写或其它读者在读,则该写者调用“WaitForSingleObject(RP_Write, INFINITE);”后将阻塞在此// 等待RP_Write信号量释放后,才能够继续向下执行。
操作系统:读者-写者问题(C语言winapi)
操作系统:读者-写者问题(C语⾔winapi)要求实现:1. 创建⼀个控制台进程,此进程包含n个线程。
⽤这n个线程来表⽰n个读者或写者。
每个线程按相应测试数据⽂件的要求进⾏读写操作。
⽤信号量机制分别实现读者优先和写者优先的读者-写者问题。
2. 读者-写者问题的读写操作限制(包括读者优先和写者优先):1. 写-写互斥,即不能有两个写者同时进⾏写操作。
2. 读-写互斥,即不能同时有⼀个线程在读,⽽另⼀个线程在写。
3. 即可以有⼀个或多个读者在读。
3. 读者优先的附加限制:如果⼀个读者申请进⾏读操作时已有另⼀个读者正在进⾏读操作,则该读者可直接开始读操作。
4. 写者优先的附加限制:如果⼀个读者申请进⾏读操作时已有另⼀写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
5. 运⾏结果显⽰要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显⽰⼀⾏提⽰信息,以确定所有处理都遵守相应的读写操作限制。
测试数据⽂件格式:测试数据⽂件包括n⾏测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每⾏测试数据包括四个字段,各个字段间⽤空格分隔。
第⼀字段为⼀个正整数,表⽰线程序号。
第⼆字段表⽰相应线程⾓⾊,R表⽰读者,W表⽰写者。
第三字段为⼀个正数,表⽰读写操作的开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。
第四字段为⼀个正数,表⽰读写操作的持续时间。
当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。
下⾯是⼀个测试数据⽂件的例⼦:2 W 4 53 R 5 24 R 6 55 W 5.1 3注意:在创建数据⽂件时,由于涉及到⽂件格式问题,最好在记事本中⼿⼯逐个键⼊数据,⽽不要拷贝粘贴数据,否则,本⽰例程序运⾏时可能会出现不可预知的错误。
代码:⽤信号量实现,可先写出P/V操作的伪代码,再根据伪代码翻译C代码。
操作系统读者写者问题 源代码
在linux环境下运行!#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#include<errno.h>#include<stdlib.h>#include<stdio.h>#include<unistd.h>union semun{int val;struct semid_ds *buf;unsigned short *array;struct seminfo *_buf;};int *readcount;static int shmid,semid,s;int main(){key_t semkey,shmkey,skey;union semun arg;if((semkey=ftok(".",0x16))==-1) printf("error1\n") ;if((skey=ftok(".",0x36))==-1) printf("error3\n");if((shmid=shmget(IPC_PRIVATE,1024,0600|IPC_CREAT))==-1) printf("error4\n"); if((shmat(shmid,NULL,0))==-1) printf("error!\n");readcount=(int *)shmat(shmid,NULL,0);semid=semget(semkey,1,0600|IPC_CREAT);s=semget(skey,1,0600|IPC_CREAT);arg.val=1;semctl(semid,0,SETVAL,arg);semctl(shmid,0,SETVAL,arg);semctl(s,0,SETVAL,arg);int initsem(int key){return(semget(key,1,0600|IPC_CREAT|IPC_EXCL));}int P(int semidd,int semnun){struct sembuf sops={semnun,-1,SEM_UNDO};return(semop(semidd,&sops,1));}int V(int semidd,int semnun){struct sembuf sops={semnun,+1,SEM_UNDO};return(semop(semidd,&sops,1));}void writer(int k){while(k>0){P(s,0);P(semid,0);if(*readcount==0) P(shmid,0);(*readcount)++;V(semid,0);V(s,0);printf("XIE jing c\n");P(semid,0);(*readcount)--;;if((*readcount)==0) V(shmid,0); V(semid,0);k--;}}void reader(int j){while(j>0){P(s,0);P(shmid,0);printf("DU jing c\n");V(shmid,0);V(s,0);j--;}}writer(5);reader(6);return 0;}。
读者写者--C
生产者/消费者,读者/写者问题是探讨如何控制进程并发时经常使用到的两个模型,在这两个模型中通过使用P,V原语可达到进程控制的目的。
信号量semaphore 的定义如下:struct semaphore {int count;queue_type queue;}count的含义是:当count>=0时代表了挂起(suspended)前可以执行的进程数目,当count<0时count的模代表了queue队列中挂起的进程数目。
queue表示的是等待在这个信号量上的进程队列。
针对上述定义,可以写出P,V的伪代码如下:void wait(semaphore s){s.count--;if(s.count < 0){place this process in s.queue;block this process;}}void signal(semaphore s){s.count++;if(s.count <= 0){remove a process P from s.queue;place process P on ready list;}}针对以上P,V原语,可以解决缓冲区有限制的生产者/消费者问题,伪代码如下:const int size_of_buffer = /* buffer size */;semaphore s = 1;semaphore s = 0;semaphore e = size_of_buffer;void producer(){while(true){produce();wait(e);wait(s);append();signal(s);signal(n);}}void consume(){while(true){wait(n);wait(s);take();signal(s);signal(e);consume();}}void main(){parbegin(producer, consumer)}针对读者/写者的模型,首先要阐明的是前面所说的生产者/消费者模型并不是读者/写者的特殊情况,也就是只有一个读者(消费者),只有一个写者(生产者)的情况。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
读者——写者问题 C++程序 (原创作品)
演示效果图:
程序完整代码: #include <windows.h> #include <iostream.h> #include <fstream.h> #include <string.h> #include<string> #include<stdlib.h>//包含清屏头文件 //全局变量 int empty=1;//信号量 int wrIn=1;//信号量 int max; int temp[30]; int *wait,*next; int count=0;//记录已经完成操作的线程数 int waitSemapore; int type;//类型记录 int writc=1; int readc=1;
outfile.close(); count++; //wrIn++;//V 操作改变信号量 //empty++;//V 操作改变信号量 }//////////////////////////////////////////////////////////////写者函数结尾
void codeIn()///////////////////////////////////////////////////////////////// 输入界面 { int ru; cout<<"请输入你要创建多少个线程:"<<endl; cin>>max; for(int i=0;i<max;i++) { cout<<"你所要创建的第"<<i+1<<"个线程类型为:1.读者 2.写者"<<endl; cin>>ru;/////////////// if(ru==1||ru==2) temp[i]=ru; else cout<<"输入有误!请重新输入"<<endl;/////////////判断错误 if(i==max-1)//录入最后一个线程类型操作 { //system("cls");//清屏 HANDLE hOut; hOut = GetStdHandle(STD_OUTPUT_HANDLE); //设置输出字体颜色 red SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY); cout<<endl<<"输入完毕!"<<endl; hOut = GetStdHandle(STD_OUTPUT_HANDLE); //设置输出字体背景 SetConsoleTextAttribute(hOut, BACKGROUND_GREEN | BACKGROUND_INTENSITY); for//////////////////输出录入结果 {cout<<"线程"<<j+1<<"为:"; if(temp[j]==1)cout<<"读者"<<endl; else cout<<"写者"<<endl; }///////////////////////////////输出录入结果 cout<<"下面将进行动态演示:"<<endl<<endl;
void reader()/////////////////////////////////////////////////////读者函数开始 { empty--;//P 操作改变信号量 cout<<"读者获得资源"<<"("; SYSTEMTIME sys; GetLocalTime(&sys);//输出系统时间 cout<<" 系 统 时 间 : "<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<":"<<sys.wMilliseconds<<")"< <endl; cout<<endl<<"*"<<"读者正在进行读操作..."<<endl; //empty++;//信号量 count++; }/////////////////////////////////////////////////////////读者函数结尾
system("pause"); cout<<endl; }//录入最后一个线程类型操作 }//录入界面结束} }/////////////////////////////////////////////////////////codeIn()
int main()/////////////////////////////////////////////////主函数 { codeIn();//录入界面 wait=&temp[0]; while(wait<&temp[max]&&count<max) { waitSemapore=1; next=wait; while(*next==1||*next==2)//线程调用算法 { if(*next==1)//reader {if(empty==1||(empty==0&&wrIn==1&&*wait!=2))//体现写者优先 {reader();//调用读者函数 type=1;} else {cout<<"["<<"读者此时正在等待资源"<<"]"<<endl; //Sleep(5000);//////////////////////////////////////////////////////////// ////////////////////////////////sleep() if(waitSemapore==1) {wait=next;//////////this reader is waiting,locate it. waitSemapore--; } } } else//writer { if(empty==1) {writer();//调用写者函数 type=2;} else { cout<<"["<<"写者此时正在等待资源"<<"]"<<endl;
//Sleep(5000);//////////////////////////////////////////////////////////////// /////////////////////////////sleep() if(waitSemapore==1)///////////this writer is waiting,find it's location. {wait=next; waitSemapore--; } } }//writer is end next++; }//1while() if(type==1) {cout<<"~"<<"读者"<<readc<<"读完毕,释放资源"<<endl; readc++; empty++;//读者用的,但是为了在输出时演示出运行状态,不得不将其放在此处 Sleep(3000);////////////////////////////////////////////////////////////////// ///////////////////////////sleep() cout<<endl; } else if(type==2) { cout<<"~"<<"写者"<<writc<<"写完毕,释放资源" << endl; writc++; wrIn++;//V 操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放 在此处 empty++;//V 操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放 在此处 Sleep(3000);////////////////////////////////////////////////////////////////// ///////////////////////////sleep() cout<<endl; } }//2while() return 0; }/////////////////////////////////////////////////////主函数结束
void writer()//////////////////////////////////////////////////写者函数开始 { empty--;//P 操作改变信号量 wrIn--;//P 操作改变信号量 cout << " 写者"<<writc<<"获得资源" <<"("; SYSTEMTIME sys; GetLocalTime(&sys);//输出系统时间 cout<<" 系 统 时 间 : "<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<":"<<sys.wMilliseconds<<")"< <endl; cout<<"请输入线程要写入的内容,以/结尾"<<endl; char ch='a'; ofstream outfile("f.txt",ios::out|ios::app); if(!outfile) { cerr<<"open file error!"<<endl; abort(); } while(ch!='/') { cin>>ch; outfile<<ch; } cout<<endl<<"*" <<"写者"<<writc<<"正在进行写操作.." << endl;