现在的位置: 首页 > 综合 > 正文

Windows操作系统实习之读者-写者问题

2013年09月15日 ⁄ 综合 ⁄ 共 9386字 ⁄ 字号 评论关闭

实习环境:

系统为Windows XP + VC 6.0

实习目标:

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

读者-写者问题的操作限制(包括读者优先和写者优先):

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

2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。

3)读-读互斥,即可以有一个或多个读者在读。

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

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

测试文件格式说明,下面是一个测试数据文件的例子:

1 R 3 5
2 W 4 5
3 R 5 2
4 R 6 5
5 W 5.1 3
6 R 15 4
7 R 15 4

程序代码:

// file Prj1.cpp
// author: Melody_1208
// date: 2008-1-6
//
/////////////////////////////////////////////////////////

#include "windows.h"
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream.h>

#define READER 'R'    // reader
#define WRITER 'W'    // writer
#define INTE_PER_SEC 1000  // interrupt number per second
#define MAX_THREAD_NUM 64  // max thread number

int readcount = 0;
int writecount = 0;

CRITICAL_SECTION RP_Write;  // Critical Section
CRITICAL_SECTION cs_Write;
CRITICAL_SECTION cs_Read;

struct ThreadInfo
{
 int serial;  // the serial number of the thread.
 char entity; // type of thread(reader or writer).
 double delay; // delay of thread.
 double persist; // time fo thread's read and write operation.
};

void RP_ReaderThread(void *p);
void RP_WriterThread(void *p);
void ReaderPriority(char * file);

void WP_ReaderThread(void *p);
void WP_WriterThread(void *p);
void WriterPriority(char * file);

// the main function
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 choice(1,2 or 3): ");
  // input is incorrect.
  do{
   ch = (char)_getch();
  }while(ch != '1' && ch != '2' && ch != '3');

  // clear the screen.
  system("cls");
  // choose 3, return.
  if(ch == '3')
   return 0;
  // choose 1, reader first.
  else if(ch == '1')
   ReaderPriority("thread.dat");
  // choose 2, writer first.
  else
   WriterPriority("thread.dat");
  // end.
  printf("/nPress Any Key To Continue:");
  _getch();
  system("cls");
 }
 
 return 0;
}

void RP_ReaderThread(void *p)
{
 // execlusive object
 HANDLE h_Mutex;
 h_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex_for_readcount");

 DWORD wait_for_mutex;  // wait for the execlusive object
 DWORD m_delay;    // delay time
 DWORD m_persist;   // the time of read file operation
 int m_serial;    // serial number of the thread

 // get the information from the parameter.
 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);    // wait for a little while.

 printf("Reader thread %d sents the reading require./n", m_serial);

 // wait for execlusive signal,
 wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
 // add the reader's number
 readcount++;
 if(readcount == 1)
 {
  // the first reader,wait for resource.
  EnterCriticalSection(&RP_Write);
 }
 ReleaseMutex(h_Mutex);  // release execlusive signal

 // read the file.
 printf("Reader thread %d begins to read file./n", m_serial);
 Sleep(m_persist);

 // exit the thread
 printf("Reader thread %d finished reading file./n", m_serial);
 wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
 // decrement the reader's number
 readcount--;
 if(readcount == 0)
 {
  // if all readers finished their operation, wake up the writer
  LeaveCriticalSection(&RP_Write);
  printf("Reader thread %d leave the critical section./n", m_serial);
 }
 ReleaseMutex(h_Mutex);  // release the execlusive signal
}

void RP_WriterThread(void *p)
{
 DWORD m_delay;
 DWORD m_persist;
 int m_serial;
 // get infomation from the parameter.
 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);   // wait
 
 printf("Writer thread %d sents the writing require./n", m_serial);
 // wait for the resource
 EnterCriticalSection(&RP_Write);

 // write the file
 printf("Writer thread %d begins to write to the file./n", m_serial);
 Sleep(m_persist);

 // exit the thread
 printf("Writer thread %d finishing writing to the file./n", m_serial);

 // release the resource
 LeaveCriticalSection(&RP_Write);
}

void ReaderPriority(char * file)
{
 DWORD n_thread = 0;  // number of threads
 DWORD thread_ID;  // thread ID
 DWORD wait_for_all;  // wait for all threads

 // execlusive object
 HANDLE h_Mutex;
 h_Mutex = CreateMutex(NULL, FALSE, "mutex_for_readcount");

 // the array of the thread object
 HANDLE h_Thread[MAX_THREAD_NUM];
 ThreadInfo thread_info[MAX_THREAD_NUM];

 readcount = 0;   // Initialize readcount
 InitializeCriticalSection(&RP_Write);
 ifstream inFile;
 inFile.open(file);
 printf("Reader Priority:/n/n");
 while(inFile)
 {
  // read every writer,reader's information
  inFile>>thread_info[n_thread].serial;
  inFile>>thread_info[n_thread].entity;
  inFile>>thread_info[n_thread].delay;
  inFile>>thread_info[n_thread++].persist;
  inFile.get();
 }
 for(int i = 0; i < (int)(n_thread); i++)
 {
  if(thread_info[i].entity == READER || thread_info[i].entity == 'r')
  {
   // create reader thread
   h_Thread[i] = CreateThread(NULL, 0,
    (LPTHREAD_START_ROUTINE)(RP_ReaderThread),
    &thread_info[i],
    0, &thread_ID);
  }
  else
  {
   h_Thread[i] = CreateThread(NULL, 0,
    (LPTHREAD_START_ROUTINE)(RP_WriterThread),
    &thread_info[i],
    0, &thread_ID);
  }
 }

 // wait for all thread to terminate.
 wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
 printf("All reader and writer have finished operating./n");
}

void WP_ReaderThread(void *p)
{
 // execlusive object
 HANDLE h_Mutex1;
 h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex1");
 HANDLE h_Mutex2;
 h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex2");

 DWORD wait_for_mutex1;  // wait for the mutex1
 DWORD wait_for_mutex2;
 DWORD m_delay;    // latency time
 DWORD m_persist;   // the time it used for reading the file
 int m_serial;    // the serial number of the thread
 // get information from the parameter
 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);    // wait for a while

 printf("Reader thread %d sents the reading require./n", m_serial);
 wait_for_mutex1 = WaitForSingleObject(h_Mutex1, -1);

 // enter the reader's critical section
 EnterCriticalSection(&cs_Read);

 // block execlusive object mutex2, ensure the access,modify to readcount is
 // execlusive.
 wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1);
 // modify the reader's number
 readcount++;
 if(readcount == 1)
 {
  // if it is the first reader, wait for the writer finish
  EnterCriticalSection(&cs_Write);
 }
 ReleaseMutex(h_Mutex2);  // release the execlusive signal mutex2
 // let other reader enter the critical section
 LeaveCriticalSection(&cs_Read);
 ReleaseMutex(h_Mutex1);
 // read file
 printf("Reader thread %d begins to read file./n", m_serial);
 // block execlusive object mutex2, ensure the access, modify to readcount
 // is execlusive.
 wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1);
 readcount--;
 if(readcount == 0)
 {
  // the last reader, wake up writer
  LeaveCriticalSection(&cs_Write);
 }
 ReleaseMutex(h_Mutex2);  // release execlusive signal
}

void WP_WriterThread(void *p)
{
 DWORD m_delay;
 DWORD m_persist;
 int m_serial;
 DWORD wait_for_mutex3;
 HANDLE h_Mutex3;
 h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex3");

 // get information from the parameter
 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);  // latency wait
 printf("Writer thread %d sents the writing require./n", m_serial);

 // block execlusive object mutex3, ensure the access,modify to writecount
 // is execlusive.
 wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);
 writecount++;  // modify the number of writer
 if(writecount == 1)
 {
  // the first writer, wait for the reader finish.
  EnterCriticalSection(&cs_Read);
 }
 ReleaseMutex(h_Mutex3);

 // enter the writer critical section
 EnterCriticalSection(&cs_Write);

 // write the file
 printf("Writer thread %d begins to write to the file./n", m_serial);
 Sleep(m_persist);

 // exit the thread.
 printf("Writer thread %d finishing writing to the file./n", m_serial);
 // leave the critical section
 LeaveCriticalSection(&cs_Write);

 wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);
 writecount--;
 if(writecount == 0)
 {
  // writer finished, reader can read.
  LeaveCriticalSection(&cs_Read);
 }
 ReleaseMutex(h_Mutex3);
}

void WriterPriority(char * file)
{
 DWORD n_thread = 0;
 DWORD thread_ID;
 DWORD wait_for_all;

 // execlusive object
 HANDLE h_Mutex1;
 h_Mutex1 = CreateMutex(NULL, FALSE, "mutex1");
 HANDLE h_Mutex2;
 h_Mutex2 = CreateMutex(NULL, FALSE, "mutex2");
 HANDLE h_Mutex3;
 h_Mutex3 = CreateMutex(NULL, FALSE, "mutex3");

 // thread object
 HANDLE h_Thread[MAX_THREAD_NUM];
 ThreadInfo thread_info[MAX_THREAD_NUM];

 readcount = 0;
 writecount = 0;
 InitializeCriticalSection(&cs_Write);
 InitializeCriticalSection(&cs_Read);
 ifstream inFile;
 inFile.open(file);
 printf("Writer Priority:/n/n");
 while(inFile)
 {
  inFile>>thread_info[n_thread].serial;
  inFile>>thread_info[n_thread].entity;
  inFile>>thread_info[n_thread].delay;
  inFile>>thread_info[n_thread++].persist;
  inFile.get();
 }
 for(int i = 0; i < (int)(n_thread); i++)
 {
  if(thread_info[i].entity == READER || thread_info[i].entity == 'r')
  {
   // create reader thread
   h_Thread[i] = CreateThread(NULL, 0,
    (LPTHREAD_START_ROUTINE)(WP_ReaderThread), &thread_info[i],
    0, &thread_ID);
  }
  else
  {
   // create writer thread
   h_Thread[i] = CreateThread(NULL, 0,
    (LPTHREAD_START_ROUTINE)(WP_WriterThread),
    &thread_info[i],
    0, &thread_ID);
  }
 }

 wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
 printf("All reader and writer have finished operating./n");
}

 运行结果:

结果分析:

Writer thread 2 sents the write require.

当写者2发出申请时,有读者1在读文件,所以写者2阻塞。

Reader thread 3 sents the reading require.

Reader thread 3 begins to read file.

读者3发出申请后,立刻得到满足。

读者6和读者7发送请求时已没有读者线程,所以他们被安排在写者线程完成写操作后读文件。

习题:

用P,V操作实现多个生产者-消费者问题。

有兴趣的话可以做一下这个习题,加深对线程,同步及互斥的理解,我将在以后的内容中给出我的想法。

抱歉!评论已关闭.