Windows作業系統實習之讀者-寫者問題

來源:互聯網
上載者:User

實習環境:

系統為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操作實現多個生產者-消費者問題。

有興趣的話可以做一下這個習題,加深對線程,同步及互斥的理解,我將在以後的內容中給出我的想法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.