读者写者实验报告

 操作系统原理

 实验报告

 实验名称: :

 操作系统

 姓

 名: :

 XXX

 学

 号:

 xx x x xxxx x xx

 班

 级:

 xxx

 指导老师:

 xxx

 一、实验内容

 在Windows2000 环境下,创建一个控制台进程,此进程包含 n 个线程。用这 n个线程来表示 n 个读者或写者。每个线程按相应测试数据文件(后面有介绍)得要求进行读写操作。用信号量机制分别实现读者优先与写者优先得读者—写者问题。):)先优者写与先优者读括包(制限作操写读得题问者写—者读ﻫ1互写—写ﻫ斥,即不能有两个写者同时进行写操作。

 2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写.,)3允读-读ﻫ许,即可以有一个或多个读者在读. 读者优先得附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。请申者读个一果如:制限加附得先优者写ﻫ进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

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

 在 Windows2000 环境下,创建一个控制台进程,此进程包含n个线程。用这 n 个线程来表示 n 个读者或写者.每个线程按相应测试数据文件(后面有介绍)得要求进行读写操作。用信号量机制分别实现读者优先与写者优先得读者-写者问题。

 三、实验原理

 1) 、读者优先 读者优先指得就是除非有写者在写文件,否则读者不需要等待.所以可以用一个

 整型变量read_count 记录当前得读者数目,用于确定就是否需要释放正在等待得写者线程(当 read_count=O时,表明所有得读者读完,需要释放写者等待队列中得一个写者)。每一个读者开始读文件时,必须修改 read_count 变量.因此需要一个互斥对象mutex来实现对全局变量read_count 修改时得互斥。ﻫ另外,为了实现写—写互斥,需要增加一个临界区对象 write。当写者发出写请求时,必须申请临界区对象得所有权。通过这种方法,也可以实现读-写互斥,当read_count=l 时(即第一个读者到来时),读者线程也必须申请临界区对象得所有权。

 当读者拥有临界区得所有权时,写者阻塞在临界区对象 write 上.当写者拥有临界区得所有权时, 第一个读者判断完 "read_count==1"后阻塞在 write 上,其余得读者由于等待对read_count得判断,阻塞在 mutex 上。

 )2ﻫ 2)先 、写者优先它,来到者写个一旦一于在处之同不;似类先优者读与先优者写ﻫ应该尽快对文件进行写操作,如果有一个写者在等待,则新到来得读者不允许进行读操作。为此应当添加一个整型变量write_count,用于记录正在等待得写者得数目,当write_count=O 时,才可以释放等待得读者线程队列.全对了为ﻫ局变量 write_count 实现互斥,必须增加一个互斥对象mutex3.现实了为ﻫ写者优先,应当添加一个临界区对象 read,当有写者在写文件或等 待时,读者必须阻塞在read 上。

 · 读者线程除了要对全局变量 read_count 实现操作上得互斥外,还必须有一个互斥对象对阻塞,read 这一过程实现互斥。这两个互斥对象分别命名为mutex1与 mutex2。

 四、实验过程

 在 Windows2000 环境下,创建一个控制台进程。

 用 VC++实现。

 读者优先指得就是除非有写者在写文件,否则读者不需要等待。所以可以用一个整型变量 read_count 记录当前得读者数目,用于确定就是否需要释放正在等待得写者线程(当read_count=O 时,表明所有得读者读完,需要释放写者等待队列中得一个写者)。每一个读者开始读文件时,必须修改 read_count变量.因此需要一个互斥对象 mutex 来实现对全局变量read_count 修改时得互斥。

 另外,为了实现写—写互斥,需要增加一个临界区对象 write。当写者发出写请求时,必须申请临界区对象得所有权。通过这种方法,也可以实现读-写互斥,当read_count=l 时(即第一个读者到来时),读者线程也必须申请临界区对象得所有权. 当读者拥有临界区得所有权时,写者阻塞在临界区对象 write 上。当写者拥有临界区得所有权时, 第一个读者判断完 "read_count==1”后阻塞在 write上,其余得读者由于等待对read_count 得判断,阻塞在 mutex 上。

 写者优先与读者优先类似;不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来得读者不允许进行读操作。为此应当添加一个整型变量write_count,用于记录正在等待得写者得数目,当 write_count=O 时,才可以释放等待得读者线程队列.量变局全对了为ﻫwrite_count 实现互斥,必须增加一个互斥对象mutex3.,先优者写现实了为ﻫ应当添加一个临界区对象 read,当有写者在写文件或等在塞阻须必者读,时待ﻫread 上。

 · 读者线程除了要对全局变量 read_count实现操作上得互斥外,还必须有一个

 互斥对象对阻塞,read 这一过程实现互斥。这两个互斥对象分别命名为mutex1与 mutex2。

 结构:

 头文件 定义全局变量 RP_ReaderThread()读者优先—--读者线程 RP_WriterThread()读者优先--—写者线程 ReaderPriority ()读者优先处理函数 WP_ReaderThrea ()写者优先-——读者线程 WP_WriterThread()写者优先-——写者线程 WriterPriority ()写者优先处理函数 主函数:包含对 dat 文件得读取以及函数得调用. 代码:附录 五、实验结果

 界面:

 测试数据:

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

 结果 读者优先

 写者优先

 六、实验心得体会

 通过对读者写者问题得编程,对线程有了更深得了解,希望在后面得学习中懂得更多。

 七、参考文献

 老师提供得资料,以及互联网查阅。

 八、附录

 #include ”windows、h" #include <conio、h> #include 〈stdlib、h〉 #include 〈fstream、h〉 #include <io、h> #include <string、h〉 #include <stdio、h〉 #include "winbase、h” #define READER

 "R"

 // 读者 #define WRITER

 ’W"

 // 写者 #define INTE_PER_SEC

 1000

  // 每秒时钟中断得数目 #define MAX_THREAD_NUM

 64

  // 最大线程数 int nReaderCnt = 0;

 // 读者计数 int nWriterCnt = 0;

 // 写者计数 HANDLE hWrite

  = ::CreateSemaphore( NULL, 1, 1, NULL );

 // 写开始信号 HANDLE hRead

 = ::CreateSemaphore( NULL, 1, 1, NULL );

 // 读开始信号

 HANDLE hRCMutex

  = ::CreateMutex( NULL, FALSE, NULL );

 HANDLE hWCMutex

  = ::CreateMutex( NULL, FALSE, NULL ); HANDLE hReadMutex

  = ::CreateMutex( NULL, FALSE, NULL ); // 从测试数据文件中获取得线程信息 struct ThreadInfo {

  ThreadInfo()

  {

  nSerialNo

  = 0;

  cType

  = ’^’;

  dDelayTime

 = 0、0;

  dOpeTime

 = 0、0;

  }

  int

  nSerialNo;

  // 线程序号

  char

 cType;

  // 线程类别

  double

 dDelayTime;

 // 线程延迟时间

  double

 dOpeTime;

 // 线程读写操作时间 }; // 读者优先—-—读者线程

 // P:读者线程信息 void RP_ReaderThread(void *p)

 {

  int nSerialNo = ((ThreadInfo*)(p))-〉nSerialNo ; //从文件中读取 线程序号

  DWORD dwReadTime = (DWORD)(((ThreadInfo*)(p))—>dOpeTime * INTE_PER_SEC );

  DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))->dDelayTime * INTE_PER_SEC );

  Sleep( dwDelay );

  printf(”Reader thread %d sents the reading require、\n",nSerialNo);

  WaitForSingleObject( hRCMutex, INFINITE );

  nReaderCnt++;

  if( nReaderCnt == 1 )

  {

  WaitForSingleObject( hWrite, INFINITE );

  }

  ReleaseMutex(hRCMutex);

  printf( "Reader thread %d begins to read file、\n", nSerialNo );

  Sleep( dwReadTime );

 printf( ”Reader thread %d finished reading file、\n", nSerialNo );

  WaitForSingleObject( hRCMutex, INFINITE );

  nReaderCnt——;

  if( nReaderCnt == 0 )

  {

  ReleaseSemaphore( hWrite, 1, NULL );

  }

  ReleaseMutex(hRCMutex); } // 读者优先—--写者线程 // P:写者线程信息 void RP_WriterThread(void *p) {

  int nSerialNo = ((ThreadInfo*)(p))->nSerialNo ; //

 从参数中获得信息

  DWORD dwWriteTime = (DWORD)(((ThreadInfo*)(p))-〉dOpeTime * INTE_PER_SEC );

  DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))—>dDelayTime * INTE_PER_SEC );

  Sleep( dwDelay );

  printf("Write thread %d sents the writing require、

 \n”,nSerialNo);

  WaitForSingleObject( hWrite, INFINITE );

  printf( ”Writer thread %d begins to write to the file、\n”, nSerialNo );

  Sleep( dwWriteTime );

  printf( ”Write thread %d finished writing to the file、\n", nSerialNo );

  ReleaseSemaphore( hWrite, 1, NULL ); } // 读者优先处理函数 // file:文件名 void ReaderPriority( char *file )

 {

  int nThreadCnt = 0;

  DWORD dwThreadID = 0;

 nReaderCnt = 0;

 // 初始化读写者计数

  HANDLE hThreads[MAX_THREAD_NUM];

  ThreadInfo oThreadInfo[MAX_THREAD_NUM];

  ifstream inFile;

  in ( file );

  printf( "Reader Priority:\n\n” );

  while( inFile )

 {

  // 读入每一个读者,写者得信息

  inFile>>oThreadInfo[nThreadCnt]、nSerialNo;

  inFile〉〉oThreadInfo[nThreadCnt]、cType;

  inFile〉〉oThreadInfo[nThreadCnt]、dDelayTime;

  inFile>〉oThreadInfo[nThreadCnt]、dOpeTime;

  if ( ’^’ != oThreadInfo[nThreadCnt]、cType )

  {

  nThreadCnt++;

  }

  in();

  }

 // 创建线程

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

  {

  if(( oThreadInfo[i]、cType==READER )

 || ( oThreadInfo[i]、cType == ’r" ))

  {

  hThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(RP_ReaderThread),

 // 创建读者进程

  &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID );

 }

  else

 {

  hThreads[i] = CreateThread( NULL, 0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),// 创建写线程

 &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID );

  }

  }

  for( i = 0; i〈 nThreadCnt; i++ )

  {

  ResumeThread( hThreads[i] );

  }

  WaitForMultipleObjects( nThreadCnt, hThreads, TRUE, INFINITE );

  printf( "All reader and writer have finished operating、\n" ); } // 写者优先—-—读者线程 // P:读者线程信息 void WP_ReaderThread( void *p ) {

 int nSerialNo = ((ThreadInfo*)(p))—〉nSerialNo ; // 从参数中得到信息

  DWORD dwReadTime = (DWORD)(((ThreadInfo*)(p))—〉dOpeTime * INTE_PER_SEC );

  DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))—>dDelayTime * INTE_PER_SEC );

  Sleep( dwDelay );

  printf("Reader thread %d sents the reading require、\n",nSerialNo);

  WaitForSingleObject( hReadMutex, INFINITE );

  WaitForSingleObject( hRead, INFINITE );

  WaitForSingleObject( hRCMutex, INFINITE );

  nReaderCnt++;

  if(nReaderCnt==1)

  {

  WaitForSingleObject( hWrite, INFINITE );

  }

  ReleaseMutex( hRCMutex );

  ReleaseSemaphore( hRead, 1, NULL );

  ReleaseMutex( hReadMutex );

  printf( ”Reader thread %d begins to read file、\n", nSerialNo );

 Sleep( dwReadTime );

  printf( "Reader thread %d finished reading

 file、\n", nSerialNo );

  WaitForSingleObject( hRCMutex, INFINITE );

  nReaderCnt—-;

  if( nReaderCnt == 0 )

  {

  ReleaseSemaphore( hWrite, 1, NULL );

  }

  ReleaseMutex( hRCMutex ); } // 写者优先---写者线程 // P:写者线程信息 void WP_WriterThread( void *p ) {

  int nSerialNo = ((ThreadInfo*)(p))—>nSerialNo;

  DWORD dwWriteTime = (DWORD)

 (((ThreadInfo*)(p))->dOpeTime * INTE_PER_SEC );

  DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))->dDelayTime * INTE_PER_SEC );

  Sleep( dwDelay );

  printf("Writer thread %d sents the writing r

 equire、\n”,nSerialNo);

  WaitForSingleObject( hWCMutex, INFINITE );

  nWriterCnt++;

  if( nWriterCnt == 1 )

  {

  WaitForSingleObject( hRead, INFINITE );

  }

  ReleaseMutex(hWCMutex);

  WaitForSingleObject( hWrite, INFINITE );

  printf( "Writer thread %d begins to write to the file、\n”, nSerialNo );

  Sleep( dwWriteTime );

  printf( "Writer thread %d finished writing to the file、\n", nSerialNo );

  ReleaseSemaphore( hWrite, 1, NULL );

  WaitForSingleObject( hWCMutex, INFINITE );

  nWriterCnt--;

  if( nWriterCnt == 0 )

  {

  ReleaseSemaphore( hRead, 1, NULL );

  }

  ReleaseMutex(hWCMutex);

 } // 写者优先处理函数 // file:文件名 void WriterPriority( char * file )

 {

  int nThreadCnt = 0;

  DWORD dwThreadID;

  HANDLE hThreads[MAX_THREAD_NUM];

  ThreadInfo oThreadInfo[MAX_THREAD_NUM];

  nReaderCnt=0;

  nWriterCnt=0;

  ifstream inFile;

  in (file);

  printf(”Writer priority:\n\n”);

  while(inFile)

  {

  inFile〉>oThreadInfo[nThreadCnt]、nSerialNo;

  inFile>>oThreadInfo[nThreadCnt]、cType;

  inFile>>oThreadInfo[nThreadCnt]、dDelayTime;

  inFile>>oThreadInfo[nThreadCnt]、dOpeTime;

  if ( ’^' != oThreadInfo[nThreadCnt]、cType )

  {

 nThreadCnt++;

  }

  in();

  }

  for( int i = 0 ;i 〈 nThreadCnt; i++ ) // 创建线程

  {

  if(( oThreadInfo[i]、cType == READER ) || ( oThreadInfo[i]、cType == ’r’ ))

  {

 hThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(WP_ReaderThread),

 //创建读者进程

  &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID );

  }

  else

  {

  hThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(WP_WriterThread),

  &oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);

  }

 }

  for( i = 0; i< nThreadCnt; i++ )

  {

  ResumeThread( hThreads[i] );

  }

  WaitForMultipleObjects( nThreadCnt, hThreads, TRUE, INFINITE );

  printf("All reader and writer have finished operating、\n"); } int main(int argc,char *argv[]) {

  char ch;

  while(true)

  {

  printf(”*************************************\n");

  printf("

  1、Reader Priority\n");

  printf("

  2、Writer Priority\n");

  printf(”

  3、Exit to Windows\n");

  printf(”*************************************\n");

 printf("Enter your choice1,2,3: ");

  do{

  ch=(char)_getch();

  }while(ch!='1’&&ch!="2"&&ch!=’3’);

  system(”cls”);

  if(ch==’3")

  return 0;

  else if(ch=="1’)

  ReaderPriority(”thread、dat");

  else

  WriterPriority(”thread、dat”);

  printf(”\nPress Any Key to Coutinue:”);

  _getch();

  system(”cls");

  }

  return 0; }