当前位置:文档之家› 操作系统设计读者写者问题

操作系统设计读者写者问题

操作系统设计读者写者问题
操作系统设计读者写者问题

操作系统课程设计报告

一、操作系统课程设计任务书

读者-写者问题实现

1设计目的

通过实现经典的读者写者问题,巩固对线程及其同步机制的学习效果,加深对相关基本概念的理解,并学习如何将基本原理和实际设计有机的结合。

2 设计要求

在Windows 2000/XP环境下,使用多线程和信号量机制实现经典的读者写者问题,每个线程代表一个读者或一个写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别实现读者优先和写者优先的读者-写者问题。

读者-写者问题的读写操作限制:

(1)写-写互斥,即不能有两个写者同时进行写操作

(2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写

(3)读-读允许,即可以有二个以上的读者同时读

读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。

3 测试数据文件格式

测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。每行测试数据包括四个字段,各字段间用空格分隔。第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,R 表示读者是,W 表示写者。第三字段为一个正数,表示读写操作的开始时间。线程创建后,延时相应时间(单位为秒)后发出对共享资源

的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。下面是一个测试数据文件的例子:

1 r 3 5

2 w 4 5

3 r 5 2

4 r 6 5

5 w 5.1 3

4 相关API函数

CreateThread()在调用进程的地址空间上创建一个线程ExitThread()用于结束当前线程

Sleep()可在指定的时间内挂起当前线程

CreateMutex()创建一个互斥对象,返回对象句柄

OpenMutex()打开并返回一个已存在的互斥对象句柄,用于后续访问

ReleaseMutex()释放对互斥对象的占用,使之成为可用WaitForSingleObject()可在指定的时间内等待指定对象为可用状态

InitializeCriticalSection()初始化临界区对象EnterCriticalSection()等待指定临界区对象的所有权LeaveCriticalSection()释放指定临界区对象的所有权

文件系统的设计

通过对文件系统的设计,加深理解文件系统的内部功能及内部实现。文件系统的设计内容较多,可划分为:子目录管理、目录项结构、文件分配表(FAT)作用、创建文件、文件复制、文件头结构、程序加载方法、内存驻留(TSR)方法等,学生可相互配合,每人选做其中的某个部分。

(一)、子目录管理

1、目的:了解并掌握DOS创建和撤消子目录的方法及有关子目录操作的系统功能。

2、内容:用DOS功能调用39H和3AH来创建和撤消子目录,以及用3BH来改变当前目录。

(1)创建指定子目录

(2)撤消子目录

(3)指定子目录为当前目录

(二)、目录项结构

1、目的:了解目录项中文件属性的含义及如何修改文件属性的方法。

2、内容:用DOS功能调用43H来获取并修改文件属性。(三)、文件分配表(FAT)作用

1、目的:了解FAT作用,掌握通过FDT、FAT恢复被删除文件的方法,特别第二个FAT在恢复被删除文件中所起的作用。

2、内容:根据第二个FAT表,利用FDT的保留域快速恢复被删除文件。

(四)、创建文件

1、目的:了解如何在DOS下创建一个新文件以及由键盘上输入该文件内容的整个过程。

2、内容:由DOS功能调用建立一个文本文件,由键盘输入该文件内容。

(五)、文件复制

1、目的:掌握文件复制的一般方法及DOS文件管理功能调用的使用。

2、内容:

(1)读一个文本文件的内容,将该文件内容拷贝到另一个文件中。

(2)读源文件内容送入内存缓冲区,将缓冲区内容写入目的文件上,从而完成文件的拷贝。

(六)、文件头结构

1、目的:进一步了解EXE文件特点,掌握EXE文件添加程序的方法。

2、内容:给任意一个EXE文件添加一段程序。

(七)、程序加载方法

1、目的:了解在当前程序中加载其他程序的一般方法;加深对EXEC功能调用的掌握;了解FCB的文件操作方式;了解内存管理功能调用。

2、内容:在当前程序中调用DOS的EXEC功能,加载执行其他应用程序。

(八)、内存驻留(TSR)方法

1、目的:掌握程序驻留内存的方法,了解如何用“热键”控制所需操作及对系统时钟的获取。

2、内容:在图形模式下的屏幕右上角“弹出”一个时钟窗口,显

示出系统当前时钟的“时:分:秒”值;如果不想让时钟显示,则只要同时按下左SHIFT键和右SHIFT键,再按下ENTER健,则此时窗口被关闭;如果再想让时钟显示,只要再次同时按下左SHIFT键和右SHIFT键即可。

二、设计思路

将所有的读者和所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。

读者优先:

如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount记录当前的读者数目,用于确定是否释放写者线程,(当readcout=0 时,说明所有的读者都已经读完,释放一个写者线程),每个读者开始读之前都要修改readcount,为了互斥的实现对readcount 的修改,需要一个互斥对象Mutex来实现互斥。

另外,为了实现写-写互斥,需要一个临界区对象write,当写者发出写的请求时,必须先得到临界区对象的所有权。

通过这种方法,可以实现读写互斥,当readcount=1 时,(即第一个读者的到来时,),读者线程也必须申请临界区对象的所有权.

当读者拥有临界区的所有权,写者都阻塞在临界区对象write上。当写者拥有临界区对象所有权时,第一个判断完readcount==1 后,其余的读者由于等待对readcount的判断,阻塞在Mutex上!

写者优先:

写者优先和读者优先有相同之处,不同的地方在:一旦有一个写者到来时,应该尽快让写者进行写,如果有一个写者在等待,则新到的读者操作不能读操作,为此添加一个整型变量writecount,记录写者的数目,当writecount=0时才可以释放读者进行读操作!为了实现对全局变量writecount的互斥访问,设置了一个互斥对象Mutex3。

为了实现写者优先,设置一个临界区对象read,当有写者在写或等待时,读者必须阻塞在临界区对象read上。

读者除了要一个全局变量readcount实现操作上的互斥外,还需要一个互斥对象对阻塞在read这一个过程实现互

斥,这两个互斥对象分别为mutex1和mutex2。

程序结构

主要代码进行分析:

1、临界区:

CRITICAL_SECTION RP_Write; //临界区

CRITICAL_SECTION RP_Write_Reader;

临界区(Critical Section)是一段独占对某些共享资源访问的代码,在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。

临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION

结构对象必须经过InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。

2、定义线程结构:

struct ThreadInfo

{ int serial;

char entity;

double delay;

double persist;

};

此结构用来存放线程的信息,四个成员变量依次表示线程序号、线程类别、线程开始时间、线程读写持续时间。

3、互斥对象

创建互斥对象

CreateMutex(NULL,FALSE,"mutex_for_readcount");

参数含义如下:

NULL表示创建带有默认安全性的内核对象

FALSE表示该互斥对象没有被任何线程所拥有

mutex_for_readcount是为内核对象赋予名字。

释放互斥信号

ReleaseMutex(h_Mutex);

对资源具有访问权的线程不再需要访问此资源而要离开时,必须通过ReleaseMutex()函数来释放其拥有的互斥对象

4、创建读者线程

CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(R_ReaderTh read),

\&thread_info[i],0,&thread_ID);

参数含义如下:

NULL表示创建带有默认安全性的内核对象

0表示新读者线程拥有自己的堆栈,使用缺省大小:1MB。 (LPTHREAD_START_ROUTINE)(R_ReaderThread)表示新读者线程执行的线程函数的地址

&thread_info[i]表示在线程启动执行时将该参数传递给读者线程函数。

0表示读者线程创建后可以立即进行调度

&thread_ID表示CreateThread使用这个地址来存放系统分配

给新读者线程的I D

5、等待函数

WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);

等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止

参数含义如下:n_thread表示线程数量。

h_Thread是指向线程对象句柄的数组的指针。

ture表示:在所有线程对象变为已通知状态之前,该函数将不允许调用线程运行

参数 -1 告诉系统,调用线程愿意永远等待下去(无限时间量),直到该进程终止运行。

三、运行结果

程序运行结果如下:

***************本程序实现读者-写者问题**************

1:读者优先

2:写者优先

3:退出

****************************************************

请选择要进行的操作:

1 (回车)

读者优先:

读者线程1 发出读请求.

读者线程1 开始读文件.

写者线程2 发出写请求.

读者线程3 发出读请求.

读者线程3 开始读文件.

写者线程5 发出写请求.

读者线程4 发出读请求.

读者线程4 开始读文件.

读者线程3 完成读文件.

读者线程1 完成读文件.

读者线程 4 完成读文件.

写者线程2 开始写文件.

写者线程2 完成写文件.

写者线程5 开始写文件.

写者线程5 完成写文件.

所有的读者和写者线程完成操作.

是否还有继续? 1. 继续 2.退出

1 (回车)

***************本程序实现读者-写者问题**************

1:读者优先

2:写者优先

3:退出

**************************************************** 请选择要进行的操作:

2 (回车)

写者优先:

读者线程1 发出读请求.

读者线程1 开始读文件.

写者线程2 发出写请求.

读者线程3 发出读请求.

写者线程5 发出写请求.

读者线程4 发出读请求.

读者线程1 完成读文件.

写者线程2 开始写文件.

写者线程2 完成写文件.

写者线程5 开始写文件.

写者线程5 完成写文件.

读者线程3 开始读文件.

读者线程4 开始读文件.

读者线程3 完成读文件.

读者线程4 完成读文件.

所有的读者和写者线程完成操作.

是否还有继续? 1. 继续 2.退出

四、设计总结

本次操作系统课程设计完成的是读者-写者问题,通过学习对线程及其同步机制有了很的学习和掌握. 并认识到同步可以保证在一个时间内只有一个线程对某个资源有控制权。共享资源包括全局变量、公共数据成员或者句柄等。同步还可以使得有关联交互作用的代码按一定的顺序执行。同时也掌握了实现线程同步的对象有Critical_section(关键段),Event(事件),Mutex(互斥对象),Semaphores(信号量)并对这些对象理解如下:

对于关键段对象:首先,定义一个关键段对象;然后,初始化该对象。初始化时把对象设置为NOT_SINGALED,表示允许线程使用资源:如果一段程序代码需要对某个资源进行同步保护,则这是一段关键段代码。在进入该关键段代码前调用EnterCriticalSection函数,这样,其他线程都不能执行该段代码,若它们试图执行就会被阻塞。完成关键段的执行之后,调用LeaveCriticalSection函数,其他的线程就可以继续执行该段代码。如果该函数不被调用,则其他线程将无限期的等待。

对于互斥对象首先,调用CreateMutex创建互斥对象;然后,调用等待函数,可以的话利用关键资源;最后,调用RealseMutex 释放互斥对象。互斥对象可以在进程间使用,但关键段对象只能用于同一进程的线程之间。

对于等待函数:等待函数有:1.等待单个对象的(FOR SINGLE OBJECT): WaitForSingleObject,函数参数包括同步对象的句柄和等待时间等。如果等待时间不限制(Infinite),则只有同步对象获得信号才返回;如果等待时间为0,则在测试了同步对象的

状态之后马上返回。2.等待多个对象的(FOR MULTIPLE OBJECTS) WaitForMultipleObjects,函数参数包括同步对象的句柄,等待时间,是等待一个还是多个同步对象等等,如果等待时间不限制(Infinite),则只有同步对象获得信号才返回;如果等待时间为0,则在测试了同步对象的状态之后马上返回。

操作系统设计使我对C++有了一个很好的复习和学习,对线程的创建及同步问题及其同步对象都有了很好的理解。并能初步进行简单的程序编程。并对程序的调式过程,也使我更好了解到线程同步的具体运行过程,使我更好的理解程序。

学习语言是一个漫长的过程,我想只有在不断的实践练习中,才能更好的掌握编程的技巧,提高自己的编程能力,通过此次课设也让我深深体会到自己还有很多东西需要学习,还有很多课程需要复习。总之,此次课程设计使我收益匪浅。

五、源代码

#include

#include

#include "fstream.h"

int readcount=0; //读者数目

int writecount=0; //写者数目

CRITICAL_SECTION RP_Write; //临界区

CRITICAL_SECTION cs_Write;

CRITICAL_SECTION cs_Read;

struct ThreadInfo //线程信息

{ int Threadhao; //线程序号

char ThreadClass; //线程类别

double ThreadStartTime; //线程开始时间

double ThreadRunTime; //线程读写持续时间

};

void ReaderFun(char* file);//读者优先函数

void R_ReaderThread(void *p);//处理读者优先读者线程

void R_WriterThread(void *p);//处理读者优先写者线程

void WriterFun(char* file);

void W_ReaderThread(void *p);

void W_WriterThread(void *p);

int main()//主函数

{

char select;

while (true)

{

cout<<"***************本程序实现读者-写者问题

*******\n"<

cout<<" 1:读者优先"<

cout<<" 2:写者优先"<

cout<<" 3:退出"<

cout<<"\n**************************************** *****"<

cout<<"请选择要进行的操作:"<

do

{

cin>>select;

if(select!='1' && select!='2' && select!='3')

cout<<"你操作有误,请重试!"<

}while(select!='1' && select!='2' && select!='3');

system("cls");

if (select=='3')

return 0;//退出

else if (select=='1')//调用读者优先

ReaderFun("peizhi.txt");

else if(select=='2')//调用写者优先

WriterFun("peizhi.txt");

cout<<"\n是否还有继续? 1. 继续 2.退出"<

do

{

cin>>select;

if(select!='1' && select!='2' )

cout<<"你操作有误,请重试!"<

}while (select!='1' && select!='2');

if(select=='2')

return 0;// 退出

system("cls");

}

return 0;

}

//读者优先函数

void ReaderFun(char* file)

{

DWORD n_thread=0; //线程数初值为0

DWORD thread_ID; //线程ID

DWORD wait_for_all; //等待所有线程结束

//临界资源

HANDLE h_Mutex;

//互斥对象(h_Mutex)确保线程拥有对单个资源的互斥访问权

h_Mutex=CreateMutex(NULL,FALSE,"mutex_for_readcount" );

HANDLE h_Thread[64]; //线程对象数组,最大64

ThreadInfo thread_info[64];

readcount=0;

InitializeCriticalSection(&RP_Write); //初始化临界区

ifstream inFile;

inFile.open(file);

cout<<"读者优先:\n"<

while (inFile)

{//读入每一个读者、写者的信息

inFile>>thread_info[n_thread].Threadhao

>>thread_info[n_thread].ThreadClass

>>thread_info[n_thread].ThreadStartTime

>>thread_info[n_thread].ThreadRunTime;

if (-1 == inFile.get())

break;

n_thread++;//线程数加一

}

for (int i=0;i<(int)(n_thread);i++)

{

if (thread_info[i].ThreadClass=='r')

//创建读者线程

h_Thread[i]=CreateThread(NULL,0,\

(LPTHREAD_START_ROUTINE)(R_ReaderThread),\

&thread_info[i],0,&thread_ID);

else

//创建写者线程

h_Thread[i]=CreateThread(NULL,0,\

(LPTHREAD_START_ROUTINE)(R_WriterThread),\

&thread_info[i],0,&thread_ID);

}

wait_for_all=WaitForMultipleObjects(n_thread,h_Threa d,TRUE,-1);

cout<<"所有的读者和写者线程完成操作."<

}

//读者优先-----读者线程

void R_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_ThreadRunTime; //读文件持续时间

int m_Threadhao; //线程序号

m_Threadhao=((ThreadInfo *)(p))->Threadhao;

m_delay=(DWORD)(((ThreadInfo

*)(p))->ThreadStartTime*100);

m_ThreadRunTime=(DWORD)(((ThreadInfo

*)(p))->ThreadRunTime*100);

Sleep(m_delay); //延迟等待

cout<<"读者线程 "<

求."<

//等待互斥对象通知

wait_for_mutex=WaitForSingleObject(h_Mutex,-1); //等待互斥信号,保证对readcount的访问、

//修改互斥

readcount++; //读者数目加一

if (readcount==1)

EnterCriticalSection(&RP_Write);//禁止写者进入ReleaseMutex(h_Mutex);//释放互斥对象,允许下个读者继续读:

//读文件

cout<<"读者线程 "<

件."<

Sleep(m_ThreadRunTime);

//退出线程

cout<<"读者线程 "<

件."<

wait_for_mutex=WaitForSingleObject(h_Mutex,-1); //等待互斥信号,保证对readcount的访问、修改互斥

readcount--; //读者数目减少

if (readcount==0)

LeaveCriticalSection(&RP_Write); //如果所有读者读完,唤醒写者

ReleaseMutex(h_Mutex);//释放互斥信号

}

//读者优先-----写者线程

void R_WriterThread(void *p)

{

DWORD m_delay; //延迟时间

DWORD m_ThreadRunTime; //读文件持续时间

int m_Threadhao; //线程序号

//从参数中获得信息

m_Threadhao=((ThreadInfo *)(p))->Threadhao;

m_delay=(DWORD)(((ThreadInfo

*)(p))->ThreadStartTime*100);

m_ThreadRunTime=(DWORD)(((ThreadInfo

*)(p))->ThreadRunTime*100);

Sleep(m_delay); //延迟等待

cout<<"写者线程 "<

求."<

EnterCriticalSection(&RP_Write);//禁止下一位写者进入//写文件

cout<<"写者线程 "<

件."<

Sleep(m_ThreadRunTime);

//退出线程

cout<<"写者线程 "<

件."<

LeaveCriticalSection(&RP_Write); //如果所有读者读完,唤醒写者

}

//写者优先处理函数

void WriterFun(char* file)

{

DWORD n_thread=0; //线程数目

DWORD thread_ID; //线程ID

DWORD wait_for_all; //等待所有线程结束

//互斥对象

HANDLE h_Mutex1, h_Mutex2, h_Mutex3;

h_Mutex1 = CreateMutex(NULL, FALSE,

"mutex_for_writecount");

h_Mutex2 = CreateMutex(NULL, FALSE,

"mutex_for_readcount");

h_Mutex3 = CreateMutex(NULL, FALSE, "mutex_for_read");

//线程对象数组

HANDLE h_Thread[64];

ThreadInfo thread_info[64];

readcount=0; //初始化readcount

InitializeCriticalSection(&cs_Write); //初始化临界

InitializeCriticalSection(&cs_Read);

ifstream inFile;

inFile.open(file); //打开文件

cout<<"写者优先:\n"<

while (inFile)

{//读入每一个读者、写者的信息

inFile>>thread_info[n_thread].Threadhao

>>thread_info[n_thread].ThreadClass

>>thread_info[n_thread].ThreadStartTime

>>thread_info[n_thread].ThreadRunTime;

if(-1 == inFile.get())

break;

n_thread++;//线程数加一

}

for (int i=0;i<(int)(n_thread);i++)

{

if (thread_info[i].ThreadClass=='r')

//创建读者线程

h_Thread[i]=CreateThread(NULL,0,\

(LPTHREAD_START_ROUTINE)(W_ReaderThread),\

&thread_info[i],0,&thread_ID);

else

//创建写者线程

h_Thread[i]=CreateThread(NULL,0,\

(LPTHREAD_START_ROUTINE)(W_WriterThread),\

&thread_info[i],0,&thread_ID);

}

//等待所有线程结束

wait_for_all=WaitForMultipleObjects(n_thread,h_Threa d,TRUE,-1);

cout<<"所有的读者和写者线程完成操作."<

}

//写者优先-----写者线程

void W_WriterThread(void *p)

{

//互斥变量

HANDLE h_Mutex1;

h_Mutex1 =

OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_writecount")

;

DWORD wait_for_mutex; //等待互斥变量所有权

DWORD m_delay; //延迟时间

DWORD m_ThreadRunTime; //读文件持时续间

int m_Threadhao; //线程序号

m_Threadhao=((ThreadInfo *)(p))->Threadhao;

m_delay=(DWORD)(((ThreadInfo

*)(p))->ThreadStartTime*100);//每秒时钟中断100次

m_ThreadRunTime=(DWORD)(((ThreadInfo

*)(p))->ThreadRunTime*100); Sleep(m_delay);

cout<<"写者线程 "<

求."<

wait_for_mutex=WaitForSingleObject(h_Mutex1,-1);

writecount++;

if (writecount==1)

EnterCriticalSection(&cs_Read);

ReleaseMutex(h_Mutex1);

EnterCriticalSection(&cs_Write);

cout<<"写者线程 "<

件."<

Sleep(m_ThreadRunTime);

cout<<"写者线程 "<

件."<

LeaveCriticalSection(&cs_Write);

wait_for_mutex=WaitForSingleObject(h_Mutex1,-1);

writecount--;

if(writecount == 0)

LeaveCriticalSection(&cs_Read);

ReleaseMutex(h_Mutex1);

}

//写者优先-----读者线程

void W_ReaderThread(void *p)

{

HANDLE h_Mutex2, h_Mutex3;

h_Mutex2 =

OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");

h_Mutex3 =

OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_read");

DWORD wait_for_mutex, wait_for_mutex1;

//等待互斥变量所有权

DWORD m_delay; //延迟时间

DWORD m_ThreadRunTime; //读文件持续时间

int m_Threadhao; //线程序号

m_Threadhao=((ThreadInfo *)(p))->Threadhao;

m_delay=(DWORD)(((ThreadInfo

*)(p))->ThreadStartTime*100);

m_ThreadRunTime=(DWORD)(((ThreadInfo

*)(p))->ThreadRunTime*100);

Sleep(m_delay);

cout<<"读者线程 "<

wait_for_mutex1=WaitForSingleObject(h_Mutex3,-1);

EnterCriticalSection(&cs_Read);

LeaveCriticalSection(&cs_Read);

ReleaseMutex(h_Mutex3);

wait_for_mutex=WaitForSingleObject(h_Mutex2,-1);

readcount++;

if (readcount == 1)

EnterCriticalSection(&cs_Write);

ReleaseMutex(h_Mutex2);

cout<<"读者线程 "<

Sleep(m_ThreadRunTime);

cout<<"读者线程 "<

wait_for_mutex=WaitForSingleObject(h_Mutex2,-1);

readcount--;

if (readcount == 0)

LeaveCriticalSection(&cs_Write);

ReleaseMutex(h_Mutex2);

}

java实现读者写者问题(写着优先)

实验一实验报告 学号:20092128 姓名:徐卓远 实验序号:1 实验名称:用信号量来实现读者-写者问题 实验目的:理解进程同步与互斥的概念,掌握用信号量来实现进程的同步与互斥。 实验设计及实现: 为了实现读者和写者的读写过程,将每个读者和每个写者作为了一个单独的线程,所以设置了两个类,一个是读者类Reader,一个是写者类Writer.以读者类为例: 一个读者的动作过程为由睡眠->等待->开始读->结束读->睡眠的一个循环过程,而一个写者的动作过程也为此. 读者调用方法napping()进行等待,调用startRead()方法开始读,最后在调用endReading()方法结束读入,释放运行空间.写者同读者. 但是为了实现读者写者之间的写-写互斥,读-写互斥,读-读允许,需要另外一个类Database,类中分别用关于读者的方法和写者的方法来控制读写之间的这种关系. 首先要实现睡眠的方法napping(),读者和写者在睡眠过程都应该是一样的,只是他们睡眠的时间不同,所以只需写出一个方法: public static void napping() {

int sleepTime = (int) (NAP_TIME * Math.random()); try { Thread.sleep(sleepTime * 1000); } catch (Exception e) { e.printStackTrace(); } } 在方法中,控制线程休眠随机的时间,由于每个读者或写者都是一个线程,而每个读者或写者他们工作休眠的时间都不一定相同,他们请求工作的时间也不一定相同,所以取了随机时间其次设置了读者的两个方法,开始读和结束读,由于这只是个模拟读写问题,所以只需要知道结果就行,就不用显示出他是怎么读的. 在开始读中,当有写者在写时,读者需要等待wait(),在没有人在工作时,如果有写者和读者同时请求,那么就让写者先进,这是写者优先.所以这就归纳于一种情况, 当读者布尔变量dbReading为FALSE时,如果有需要工作的写者,那么读者就等待. 当读者请求读入后,计数有多少读者需要工作的变量readerCount +1,如果这是第一个进入工作的读者就需要将显示是否有读者在工作的读者布尔变量变为TRUE. public synchronized int startRead() { if (dbReading == false) {

读者和写者问题

学 号: 课 程 设 计 2014——2015学年 第1学期 课程名称 操作系统 学 院 计算机科学与技术学院 专 业 软件工程专业 班 级 姓 名 指导教师

目录 目录 .................................................................................................................................... 错误!未定义书签。 1 设计概述 (3) 1.1问题描述: (3) 1.2问题解读及规则制定 (3) 2课程设计目的及功能 (3) 2.1 设计目的 (3) 2.2 设计功能 (3) 3模块介绍 (3) 3.1函数原型 (3) 3.2 PV操作代码 (4) 4测试用例,运行结果与运行情况分析 (6) 4.1测试用例 (6) 4.2运行结果 (7) 4.3运行情况分析 (9) 5自我评价与总结 (9) 6 参考文献 (10) 7 附录:(完整代码) (10)

实现读者写者(Reader-Writer Problem)问题 1 设计概述 1.1问题描述: 通过研究Linux的线程机制和信号量实现读者写者(Reader-Writer)问题并发控制。 1.2问题解读及规则制定 一个数据文件或记录可被多个进程所共享,我们将其中只要求读该文件的进程称为读者,其他进程称为写者.多个读者和多个写者进程在某个时间段内对该文件资源进行异步操作,也就是说允许多个进程同时读一个共享对象,但不允许一个写进程和其他读进程或写进程同时访问共享对象,因此,所谓"读者--写者问题"就是指必须保证一个写进程和其他进程(写进程或者读进程)互斥地访问共享对象的同步问题.两者的读写操作限制规则如下: (1)写--写互斥,即不允许多个写着同时对文件进行写操作 (2)读--写互斥,即不允许读者和写者同时对文件分别进行读写操作 (3)读—读允许,即允许多个读者同时对文件进行读操作 2课程设计目的及功能 2.1 设计目的 通过实验模拟读者和写者之间的关系,了解并掌握他们之间的关系及其原理。由此增加对进程同步的问题的了解。具体如下: 1)掌握基本的同步互斥算法,理解读者和写者模型 2)了解多线程的并发执行机制,线程间的同步和互斥 2.2 设计功能: 利用模拟用信号量机制实现读者和写者问题:通过用户控制读进程和写进程,反应读者和写者问题中所涉及的进程的同步与互斥。 3模块介绍 3.1函数原型 读者和写者进程由11个函数组成,分别如下: (附件包含全部具体实现) void P_write(int); void write(int); void V_write(int); void P_radd(int);

请用PV操作解决读者和写者问题

请用PV操作解决读者和写者问题。有两组并发进程:读者和写者,共享一个文件,要求:(1)允许多个读者同时执行读操作(2)在任意写者在完成写操作之前,不允许其他任意的读者和写者工作 3写者预工作,但在它之前已有读者在执行读操作,那么,待现有读者完成读操作后在执行写操作,新的读者和写者均被拒绝。Samapher matex=1/*对文件互斥*/ S1=1/*对Readcount互斥*/ Readcount=0读者记数器。 Reader: Writer: P(S1); P(mutex); Readcount++; Write a file; V(S1); V(mutex); Read a file; P(S1); Readcount--; If(Readcount==0) V(mutex); V(S1); 设由n个缓冲区组成缓冲池,每个缓冲区可以存放一个消息,有两类进程:x个生产者和y 个消费者,且只要缓冲池未满,生产者便可以将消息送入缓冲池,而只要缓冲池未空,消费者就可以取走一个消息。各个进程对缓冲池进行互斥访问,用信号量实现协调过程。要求写出使用的信号量、初值及其作用,并写出生产者进程和消费者进程的处理流程(10分)

某寺庙共有老和尚和小和尚若干人,庙外有一口井,只能容一人打水,庙内有6只水桶和一口缸,缸内最多能装30桶水,每只桶每次只能由一人使用,缸每次只能由一人使用。小和尚负责从庙外的井里打水,老和尚使用缸里的水,老和尚取水的单位是桶。请利用信号量和P、V操作描述老和尚和小和尚的活动。semaphore empty=30; // 表示缸中目前还能装多少桶水,初始时能装30桶水 semaphore full=0; // 表示缸中有多少桶水,初始时缸中没有水 semaphore buckets=6; // 表示有多少只空桶可用,初始时有6只桶可用 semaphore mutex_well=1; // 用于实现对井的互斥操作 semaphore mutex_bigjar=1; // 用于实现对缸的互斥操作 semaphore mutex_buchet=1; // 用于实现对桶的互斥操作,防止多人同时拿同一只桶yongermonk(){ while(1){P(empty); P(buckets); P(mutex_bucket); get a bucket; V(mutex_bucket); go to the well; P(mutex_well); get water; V(mutex_well); go to the temple; P(mutex_bigjar); pure the water into the big jar; V(mutex_bigjar); V(buckets); V(full);}} oldmonk(){ while(1){P(full); P(buckets); P(mutex_bucket); get a bucket; V(mutex_bucket); P(mutex_bigjar); get water; V(mutex_bigjar); V(buckets); V(empty); } }

读者写者问题课程设计说明书

-- 数学与计算机学院 课程设计说明书 课程名称: 操作系统原理-课程设计课程代码: 题目:读者写者问题 年级/专业/班: 学生姓名: 学号: 开始时间:2011 年12月05日完成时间:2011 年12月25 日课程设计成绩: 学习态度及平时成绩(30) 技术水平与实际 能力(20) 创新(5)说明书撰写质量(45) 总分 (100) 指导教师签名:年月日

目录 1 引言?错误!未定义书签。 1.1问题的提出?错误!未定义书签。 1.2任务于分析?错误!未定义书签。 2程序的主要功能?错误!未定义书签。 2.1测试文本录入功能.................................... 错误!未定义书签。 2.2读者优先判断功能.................................... 错误!未定义书签。2.3写者优先判断功能.................................. 错误!未定义书签。 3 程序运行平台........................................... 错误!未定义书签。 4 总体设计............................................... 错误!未定义书签。5模块分析 ............................................... 错误!未定义书签。 5.1测试文本录入模块.................................... 错误!未定义书签。 5.2读者优先判断模块.................................... 错误!未定义书签。 5.3写者优先判断模块.................................... 错误!未定义书签。6系统测试............................................. 错误!未定义书签。 7 结论................................................................. 8致谢.................................................. 错误!未定义书签。参考文献 (10)

实验二 读者写者问题实验报告..

实验二读者写者问题实验报告 一、实验目的 Windows2000/XP提供了互斥量(mutex)、信号量(semapore)、事件(event)等三种同步对象和相应的系统调用,用于线程的互斥与同步。通过对读者写者问题的调试,了解Windows2000/XP中的同步机制。 二、实验内容及实验步骤 利用Windows2000/XP信号量机制,实现读者写者问题。 在Windows 2000环境下,创建一个控制台进程,此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。用信号量机制分别实现读者优先和写者优先的读者-写者问题。 读者-写者问题的读写操作限制(包括读者优先和写者优先): 写-写互斥,即不能有两个写者同时进行写操作。 读-写互斥,即不能同时有一个线程在读,而另一个线程在写。 读-读允许,即可以有一个或多个读者在读。 读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。 写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态才能开始读操作。 运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结果读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。 三、实验结果及分析 图2.1 选择界面 第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,R 表示读者是,W 表示写者。第三字段为一个正数,表示读写操作的开始时间。线程创建

后,延时相应时间(单位为秒)后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。下面是一个测试数据文件的例子: 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 测试结果如下: 图2.2 读者优先运行结果

操作系统OS报告读者与写者问题(进程同步问题)

目录 一、课程设计目的及要求 (1) 二、相关知识 (1) 三、题目分析 (2) 四、概要设计 (4) 五、代码及流程 (5) 六、运行结果 (11) 七、设计心得 (12) 八、参考文献 (12)

一、课程设计目的及要求 读者与写者问题(进程同步问题) 用n 个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别实现读者优先和写者优先的读者-写者问题。 读者-写者问题的读写操作限制: 1)写-写互斥; 2)读-写互斥; 3)读-读允许; 写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。 二、相关知识 Windows API: 在本实验中涉及的API 有: 1线程控制: CreateThread 完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。 HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD DWORD dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier ); 2 ExitThread 用于结束当前线程。 VOID ExitThread( DWORD dwExitCode // exit code for this thread ); 3Sleep 可在指定的时间内挂起当前线程。 VOID Sleep( DWORD dwMilliseconds // sleep time ); 4信号量控制: WaitForSingleObject可在指定的时间内等待指定对象为可用状态; DWORD WaitForSingleObject( HANDLE hHandle, // handle to object DWORD dwMilliseconds // time-out interval );

操作系统读者写者实验报告

《操作系统》上机实验报告 实验项目读者写者 学院(部)信息学院 专业计算机科学与技术班级 学生姓名 学号

读者写者问题 一.实验目的: 1.熟悉读者优先和写者优先的过程。 2.更好地理解进程同步的概念及其实现方法。 二.实验要求: 分别实现读者优先和写者优先。 “读-写”互斥,即不能同时有一个读者在读,同时去有一个写者在写; “写-写”互斥,即不能有两个写者同时进行写操作; “读-读”允许,即可以有两个以上的读者同时进行读操作。 三.实验内容: 读者优先: 如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount 记录当前的读者数目,用于确定是否释放写者线程,(当readcout=0 时,说明所有的读者都已经读完,释放一个写者线程),每个读者开始读之前都要修改readcount,为了互斥的实现对readcount 的修改,需要一个互斥对象Mutex来实现互斥。 另外,为了实现写-写互斥,需要一个临界区对象write,当写者发出写的请求时,必须先得到临界区对象的所有权。通过这种方法,可以实现读写互斥,当readcount=1 时,(即第一个读者的到来时,),读者线程也必须申请临界区对象的所有权. 当读者拥有临界区的所有权,写者都阻塞在临界区对象write上。当写者拥有临界区对象所有权时,第一个判断完readcount==1 后,其余的读者由于等待对readcount的判断,阻塞在Mutex上! 写者优先: 写者优先和读者优先有相同之处,不同的地方在:一旦有一个写者到来时,应该尽快让写者进行写,如果有一个写者在等待,则新到的读者操作不能读操作,为此添加一个整型变量writecount,记录写者的数目,当writecount=0时才可以释放读者进行读操作!为了实现对全局变量writecount的互斥访问,设置了一个互斥对象Mutex3。 为了实现写者优先,设置一个临界区对象read,当有写者在写或等待时,读者必须阻塞在临界区对象read上。 读者除了要一个全局变量readcount实现操作上的互斥外,还需要一个互斥对象对阻塞在read这一个过程实现互斥,这两个互斥对象分别为mutex1和mutex2。

操作系统课程设计--读者-写者问题

操作系统课程设计报告 一、操作系统课程设计任务书 读者- 写者问题实现 1设计目的通过实现经典的读者写者问题,巩固对线程及其同步机制的学习效果,加深对相关基本概念的理解,并学习如何将基本原理和实际设计有机的结合。 2设计要求 在Windows 2000/XP 环境下,使用多线程和信号量机制实现经典的读者写者问题,每个线程代表一个读者或一个写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别实现读者优先和写者优先的读者- 写者问题。 读者-写者问题的读写操作限制: (1)写-写互斥,即不能有两个写者同时进行写操作 (2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写 (3)读-读允许,即可以有二个以上的读者同时读读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。 写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。 运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。 3测试数据文件格式 测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。每行测试数据包括四个字段,各字段间用空格分隔。第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,R 表示读者是,W 表示写者。第三字段为一个正数,表示读写操作的开始时间。线程创建后,延时相应时间(单位为秒)后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时

操作系统课程设计-读者写者问题

操作系统课程设计报告

一、开题报告 (一)该项课程设计的意义; 1.更加深入的了解读者写者问题的算法; 2.加深对线程,进程的理解; 3.加深对“线程同步”概念的理解,理解并应用“信号量机制”; 4.熟悉计算机对处理机的管理,了解临界资源的访问方式; 5.了解C++中线程的实现方式,研读API。 (二)课程设计的任务 多进程/线程编程:读者-写者问题。 ●设置两类进程/线程,一类为读者,一类为写者; ●随机启动读者或写者; ●显示读者或写者执行状态; ●随着进程/线程的执行,更新显示; (三)相关原理及算法描述; 整体概况: 该程序从大体上来分只有两个模块,即“读者优先”和“写者优先”模块. 读者优先: 如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount记录读者数目,用于确定是否释放读者线程,readcount的初值为0.当线程开始调入时. 每个读者准备读. 等待互斥信号,保证对readcount 的访问,修改互斥.即readcount++. 而当读者线程进行读操作时,则读者数目减少(readcount--).当readcout=0 时,说明所 有的读者都已经读完,离开临界区唤醒写者(LeaveCriticalSection(&RP_Write);), 释 放互斥信号(ReleaseMutex(h_Mutex)). 还需要一个互斥对象mutex来实现对全局变量Read_count修改时的互斥. 另外,为了实现写-写互斥,需要增加一个临界区对象Write。当写者发出写请求时, 必须申请临界区对象的所有权。通过这种方法,可以实现读-写互斥,当 Read_count=1时(即第一个读者到来时),读者线程也必须申请临界区对象的所有 权 写者优先: 写者优先与读者不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。为此应当填加 一个整形变量write_count,用于记录正在等待的写者的数目,write_count的初值 为0.当线程开始调入时.只允许一个写者准备读. 等待互斥信号,保证对write_count 的访问,修改互斥.即write_count++.而当写者线程进行读操作时,则相应写者数目减 少(write_count--).当write_count=0 时,说明所有的读者都已经读完,离开临界区唤 醒读者,释放互斥信号. 为了实现写者优先,应当填加一个临界区对象read,当有写者在写文件或等待时,读者必须阻塞在read上。

面向对象OS读者-写者问题

2.读者—写者问题 读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求: (1)允许多个读者同时执行读操作; (2)不允许读者、写者同时操作; (3)不允许多个写者同时操作。 Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。

(1)读者优先。对于读者优先,应满足下列条件: 如果新读者到: ①无读者、写者,新读者可以读; ②有写者等待,但有其它读者正在读,则新读者也可以读; ③有写者写,新读者等待。 如果新写者到: ①无读者,新写者可以写; ②有读者,新写者等待; ③有其它写者,新写者等待。 单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数; rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下: int rc=0; //用于记录当前的读者数量 semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量 semaphore write=1; //用于保证读者和写者互斥地访问的信号量 void reader() /*读者进程*/ do{ P(rc_mutex); //开始对rc共享变量进行互斥访问 rc ++; //来了一个读进程,读进程数加1 if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区, //若有,读进程等待,若无,阻塞写进程 V(rc_mutex); //结束对rc共享变量的互斥访问 读文件; P(rc_mutex); //开始对rc共享变量的互斥访问 r c--; //一个读进程读完,读进程数减1 if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要 进入临界区,若有,唤醒一个写进程进临界区 V(rc_mutex); //结束对rc共享变量的互斥访问 } while(1) void writer() /*写者进程*/ do{ P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件; V(write); //写进程完成;判断是否有读进程需要进入临界区, //若有,唤醒一个读进程进临界区 } while(1) 读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。该算法只要还有一个读者在活动,就允许后续的读者进来,该策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入。而写者就始终被挂起,直到没有读者为止。

读者写者问题写者优先代码

读者写者问题-写者优先代码 #include<stdio.h> #include<stdlib.h> int rcount=0;//正在读的读者数量 int wcount=0;//写者队列中等待写操作的写者数量 int rid=0;//读进程号 int wid=0;//写进程号 int w=1;//读写互斥信号量 char temp[300] = {'\0'}; int sign; //标识temp空的信号量0表示temp空 void WFwakeup(); void RFwakeup(); struct rqueue{//读者等待队列 int readers[200]; int index; }rq; struct wqueue{//写者等待队列 int writers[200]; int index; }wq; void read(){ int i = 0; rid++; if(rcount == 0){//当前没有读进程在读可能有写进程在写可能CPU空闲if(w==1) {//如果CPU空闲,读者拿到CPU w--;// 相当于一个P操作 rcount++; if(temp[0] == '\0'){ sign = 0; rq.readers[rq.index++]=rid;//将读者进程加入等待队列 WFwakeup(); return; }//if printf("读者%d正在读\n",rid);

for(i = 0;i < 300;i++){//读取temp内容即写者写的内容 if(temp[i] == '\0'){ printf("\n"); return; }//if printf("%c",temp[i]); }//for }//if else{//写者线程正在执行 printf("有写者在写不能读!\n"); rq.readers[rq.index++]=rid;//将读者进程加入等待队列 }//else }//if else{//rcount !=1 则知道当前已经有读者在读,读读不互斥,则这个读者可以直接进来了读 printf("读者%d正在读\n",rid); for(i = 0;i < 300;i++){ if(temp[i] == '\0'){ printf("\n"); return; } printf("%c",temp[i]); }//for }//else } //***************************写进程写操作 void write(){ wid++; if(w == 0){ if(rcount != 0 ){//有读者进程在执行 printf("有读者在读不能写!\n"); wq.writers[wq.index++]=wid;//将写者进程加入等待队列 wcount++; return; } if(rcount == 0 ){//rcount == 0则当前无读者,但w = 0,所以有写者在写 printf("有写者在写不能写!\n"); wq.writers[wq.index++]=wid;//将写者进程加入等待队列 wcount++; return; } }

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

《计算机操作系统》实验报告 题目读者写者问题 学院(部)信息学院 专业计算机科学与技术 班级 学生姓名 学号 指导教师(签字)

一、问题描述 一个数据文件或者记录,可以被多个进程共享,我们把只要求读该文件的进程称为“Reader进程”,其他进程则称为“Writer进程”。允许多个进程同时读一个共享对象,因为读操作不会是数据文件混乱。但不允许一个Writer进程和其他Reader进程或者Writer进程同时访问共享对象,因为这种访问将会引起混乱。所谓“读者——写着问题(Reader—Writer Problem)”是指保证一个Writer进程必须与其他进程互斥地访问共享对象的同步问题 二、解决问题 为实现Reader与Writer进程间在读或写是的互斥而设置了一个互斥的信号量Wmutex。另外,在设置一个整型变量Readcount表示正在读的进程数目。由于只要有一个Reader进程在读,便不允许Writer去写。因此,仅当Readercount=0时,表示尚无Reader进程在读时,Reader进程才需要进行Wait(wmutex)操作。若Wait(Wmutex)操作成功,Reader进程便可去读,相应地,做Readcount+1操作。同理,仅当Reader进程在执行了Readercount-1操作后其值为0时,才执行Signal(Wmutex)操作,以便让Writer进程写。又因为Readercount是一个可被多个Reader进程访问的临界资源,因此也应该为它设置一个互斥信号量rmutex。 三、代码实现 1、读者优先 #include #include using namespace std; CRITICAL_SECTION rmutex,wmutex; int wr; int readernum; DWORD WINAPI reader(LPVOID IpParamter){ cout<<"读者申请\n"; wr++; EnterCriticalSection(&rmutex); if(readernum==0) EnterCriticalSection(&wmutex); readernum++; cout<<"读者进入成功正在读取\n"; LeaveCriticalSection(&rmutex); Sleep(2000); EnterCriticalSection(&rmutex); readernum--; cout<<"读者退出\n"; wr--;

读者写者问题

一设计概述 所谓读者写者问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。 读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者必写者优先,也就是说,读者和写者同时提出请求时,读者优先。当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前是否可操作。 信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则是这一机制的一个经典范例。 与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许RN个读者同时读。为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait(L,1,1)操作,来控制读者的数目,每当有一个读者进入时,就要执行wait(L,1,1)操作,使L的值减1。当有RN个读者进入读后,L便减为0,第RN+1 个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。对利用信号量来解决读者—写者问题的描述如下: Var RN integer;L,mx:semaphore: =RN,1; Begin Parbegin Reader :begin Repeat Swait(L,1,1); Swait(mx,1,0); . Perform reader operation; Ssignal(L,1); Until false; End

Writer :begin Repeat Swait(mx ,1,1,l,RN,0); Perform writer operation; Ssignal(mx,1); Until false; End Parend End 其中,Swait(mx,1,0)语句起着开关作用,只要无Writer进程进入些,mx=1,reader进程就都可以进入读。但是要一旦有Writer进程进入写时,其MX=0,则任何reader进程就都无法进入读。Swait(mx ,1,1,l,RN,0)语句表示仅当既无Write 进程在写(mx=1),又无reader进程在读(L=RN)时,writer进程才能进入临界区写。 本设计方案就是通过利用记录型信号量对读者写者问题的解决过程进行模拟演示,形象地阐述记录型信号量机制的工作原理。 二设计目的与内容 一实验目的 l. 用信号量来实现读者写者问题。 2. 理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。二、二实验内容 读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:(1)任意多个读进程可以同时读这个文件; (2)一次只有一个写进程可以往文件中写; (3)如果一个写进程正在进行操作,禁止任何读进程度文件。

题目3-读者与写者问题

实验3 读者/写者问题与进程同步 3.1 实验目的 理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的方法。 3.2 实验要求 在linux环境下编写一个控制台应用程序,该程序运行时能创建N个线程,其中既有读者线程又有写者线程,它们按照事先设计好的测试数据进行读写操作。请用信号量和PV操作实现读者/写者问题。 读者/写者问题的描述如下: 有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。以下假设共享数据区是文件。这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。这些条件具体来说就是:(1)任意多的读进程可以同时读这个文件; (2)一次只允许一个写进程往文件中写; (3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件; (4)写进程执行写操作前,应让已有的写者或读者全部退出。这说明当有读者在读文件时不允许写者写文件。 对于读者-写者问题,有三种解决方法: 1、读者优先 除了上述四个规则外,还增加读者优先的规定,当有读者在读文件时,对随后到达的读者和写者,要首先满足读者,阻塞写者。这说明只要有一个读者活跃,那么随后而来的读者都将被允许访问文件,从而导致写者长时间等待,甚至有可能出现写者被饿死的情况。 2、写者优先 除了上述四个规则外,还增加写者优先的规定,即当有读者和写者同时等待时,首先满足写者。当一个写者声明想写文件时,不允许新的读者再访问文件。 3、无优先 除了上述四个规则外,不再规定读写的优先权,谁先等待谁就先使用文件。 3.3算法分析 3.3.1读者优先 对于相继到达的一批读者,并不是每个读者都需要执行P(r_w_w)和V(r_w_w)。在这批读者中,只有最先到达的读者才需要执行P(r_w_w),与写者竞争对文件的访问权,若执行P(r_w_w)成功则获得了文件的访问权,其他的读者可直接访问文件;同理,只有最后退出临界区的读者需要执行V(r_w_w)来归还文件访问权。 为了记录正在读文件的一批读者的数量,需要设置一个整型变量readercount,每一个读者到达时都要将readercount加1,退出时都要将readercount减1。 由于只要有一个读者在读文件,便不允许写者写文件,所以,仅当readercount=0时,即尚无读者在读文件时,读者才需要执行P(r_w_w)操作。若P(r_w_w)操作成功,读者便可去读文件,相应地,readercount+1。同理,仅当在执行了readercount减1操作后其值为0时,才需要执行V(r_w_w)操作,以便让写者写文件。又因为readercount是一个可被多个读者访问的临界资源,所以应该为它设置一个互斥信号量readercount_mutex.。每个读者在访

北理工操作系统实验二读者写者问题

本科实验报告 实验名称:操作系统原理实验(读者写者问题) 课程名称:操作系统原理实验时间:2015.10.30 任课教师:王耀威实验地点:10#102 实验教师:苏京霞 实验类型: 原理验证□综合设计□自主创新 学生姓名:孙嘉明 学号/班级:1120121474/05611202 组号:学院:信息与电子学院同组搭档:专业:信息对抗技术成绩:

实验二:读者写者问题 一、实验目的 1.通过编写和调试程序以加深对进程、线程管理方案的理解; 2.熟悉Windows多线程程序设计方法; 二、实验要求 在Windows环境下,创建一个控制台进程,此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。用信号量机制分别实现读者优先和写者优先问题。 读者-写者问题的读写操作限制(包括读者优先和写者优先) 1)写-写互斥:不能有两个写者同时进行写操作 2)读-写互斥:不能同时有一个线程在读,而另一个线程在写。 3)读-读允许:可以有一个或多个读者在读。 读者优先的附加限制:如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。 运行结果显示要求:要求在每个线程创建、发出读写申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。 测试数据文件包括 n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。每行测试数据包括四个字段,每个字段间用空格分隔。第1个字段为正整数,表示线程的序号。第2个字段表示线程的角色,R表示读者,W表示写者。第3个字段为一个正数,表示读写开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。第4个字段为一个正数,表示读写操作的延迟时间。当线程读写申请成功后,开始对共享资源进行读写操作,该操作持续相应时间后结束,释放该资源。 下面是一个测试数据文件的例子(在记事本手工录入数据): 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3

操作系统课程设计读者写者问题

计算机与信息学院 操作系统课程设计报告一、开题报告 (一)该项课程设计的意义; 1.更加深入的了解读者写者问题的算法; 2.加深对线程,进程的理解; 3.加深对“线程同步”概念的理解,理解并应用“信号量机制”; 4.熟悉计算机对处理机的管理,了解临界资源的访问方式; 5.了解C++中线程的实现方式,研读API。 (二)课程设计的任务 多进程/线程编程:读者-写者问题。 ●设置两类进程/线程,一类为读者,一类为写者; ●随机启动读者或写者; ●显示读者或写者执行状态; ●随着进程/线程的执行,更新显示; (三)相关原理及算法描述; 整体概况: 该程序从大体上来分只有两个模块,即“读者优先”和“写者优先”模块. 读者优先: 如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount记录读者数目,用于确定是否释放读者线程,readcount的初值为0.当线程开始调入时.每个读者准备读. 等待互斥信号,保证对readcount 的访问,修改互斥.即readcount++.而当读者线程进行读操作时,则读者数目减少(readcount--).当readcout=0 时,说明所有的读者都已经读完,离开临界区唤醒写者(LeaveCriticalSection(&RP_Write);), 释放互斥信号(ReleaseMutex(h_Mutex)). 还需要一个互斥对象mutex来实现对全局变量Read_count修改时的互斥. 另外,为了实现写-写互斥,需要增加一个临界区对象Write。当写者发出写请求时,必须申请临界区对象的所有权。 通过这种方法,可以实现读-写互斥,当Read_count=1时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权 写者优先: 写者优先与读者不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。为此应当填加一个整形变量write_count,用于记录正在等待的写者的数目,write_count的初值为0.当线程开始调入时.只允许一个写者准备读. 等待互斥信号,保证对write_count 的访问,修改互斥.即write_count++.而当写者线程进行读操作时,则相应写者数目减少(write_count--).当write_count=0 时,说明所有的读者都已经读完,离开临界区唤醒读者,释放互斥信号. 为了实现写者优先,应当填加一个临界区对象read,当有写者在写文件或等待时,读者必须阻塞在read上。

读者写者问题

操作系统实验报告 实验:读者-写者问题 姓名:张金志 学号:U201313788 班级:通信1306班

一、实验目的: 1、熟练使用VC++6.0编译环境,调试并正确运行程序。 2、理解阅读者和写入者中出现的问题,进而掌握信号量的使用。 3、理解源程序中管理阅读者和写入者权限的算法,及相关窗口操作。 4、阅读演示程序源代码,熟悉阅读者写入者问题流程; 5、写出ReaderThread()和WriterThread()函数伪码; 二、实验原理: 1、问题描述: 有一个公用的数据集,有很多人需要访问,其中一些需要阅读其中的信息,一些需要修改其中的消息。阅读者可以同时访问数据集,而写入者只能互斥的访问数据集,不能与任何的进程一起访问数据区。 2、源程序算法实现调度说明: 要求(书上): (1)允许多个读者同时对文件进行读操作 (2)只允许一个写者对文件进行写操作 (3)任何写者完成操作前,不允许其他读者或者写者进行操作 (4)写者在进行写操作前,要让所有的读者或者写者全部退出 3、在本程序中用于表现的图形界面说明: 在程序编译运行后会出现中间一个大的圆圈表示公用的资源,上面一排五个矩形表示5个读者,下面的五个矩形表示五个写入者。每个读者和写入者都有3种状态,休息,等待和操作(读入或者写入)分别用黑颜色,绿颜色,红颜色表示休息,等待和操作。一旦操作者获得资源,可以进行读或者写,我们就划一条从操作者中心到资源中心的线,表示开始操作。

三、实验伪码 ReadThread() { i=0 While(true) { Rreadstate[i]=waiting; P(mutex); Readercount++; i++; If(readcount==1) P(write); V(mutex); Resourcestate[i]=read; Resourcestate[i]=reading; P(mutex); Readcount--; If(readcount==0) v(writeblock); V(mutex) Readerstate[i]=resting; Readersource[i]=unused; } } WriteThread(){ Writerstate[i]=resting; While(1) { writerstate[i]=waiting; P(write); Writerstate[i]=writing; Resourcestate[i]=wirte; v(writeblock);

相关主题
文本预览
相关文档 最新文档