实习1:进程同步 -- 写者优先 实习要求 在Windows 2000 环境下,创建一个包含n 个线程的控制台进程。用这n 个线程来表示n 个读者或写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别 实现读者优先和写者优先的读者-写者问题。 读者-写者问题的读写操作限制: 1)写-写互斥; 2)读-写互斥; 3)读-读允许; 读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作, 则该读者可直接开始读操作。 写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资 源,则该读者必须等到没有写者处于等待状态后才能开始读操作。 运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读 写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。 测试数据文件格式 测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写 操作的开始时间和持续时间。每行测试数据包括四个字段,各字段间用空格分隔。第一字段 为一个正整数,表示线程序号。第二字段表示相应线程角色,R 表示读者是,W 表示写者。 第三字段为一个正数,表示读写操作的开始时间。线程创建后,延时相应时间(单位为秒) 后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线程读 写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。 下面是一个测试数据文件的例子: 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5
源代码如下:
/************************************************************************/ /* 操作系统实践-- 读者写者问题 /* 写者优先算法实现 /* 时间: 2004-12.10 /* 作者: 唐良 /************************************************************************/ #include <windows.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h>
#define MAX_PERSON 100 #define READER 0 #define WRITER 1 #define END -1 #define R READER #define W WRITER
typedef struct _Person { HANDLE m_hThread; int m_nType; int m_nStartTime; int m_nWorkTime; int m_nID; }Person;
Person g_Persons[MAX_PERSON]; int g_NumPerson = 0; long g_CurrentTime= 0;
int g_PersonLists[] = { 1, R, 3, 5, 2, W, 4, 5, 3, R, 5, 2, 4, R, 6, 5, END, };
int g_NumOfReading = 0; int g_NumOfWriteRequest = 0; HANDLE g_hReadSemaphore; HANDLE g_hWriteSemaphore;
void CreatePersonList(int *pPersonList); bool CreateReader(int StartTime,int WorkTime,int ID); bool CreateWriter(int StartTime,int WorkTime,int ID); DWORD WINAPI ReaderProc(LPVOID lpParam); DWORD WINAPI WriterProc(LPVOID lpParam);
int main() { g_hReadSemaphore = CreateSemaphore(NULL,1,100,NULL); g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL);
CreatePersonList(g_PersonLists); // Create All the reader and writers printf("Created all the reader and writer\n...\n"); g_CurrentTime = 0; while(true) { g_CurrentTime++; Sleep(300); // 300 ms printf("CurrentTime = %d\n",g_CurrentTime); } return 0; }
void CreatePersonList(int *pPersonLists) { int i=0; int *pList = pPersonLists; bool Ret; while(pList[0] != END) { switch(pList[1]) { case R: Ret = CreateReader(pList[2],pList[3],pList[0]); break; case W: Ret = CreateWriter(pList[2],pList[3],pList[0]); break; } if(!Ret) printf("Create Person %d is wrong\n",pList[0]); pList += 4; // move to next person list } }
DWORD WINAPI ReaderProc(LPVOID lpParam) { Person *pPerson = (Person*)lpParam; // wait for the start time while(g_CurrentTime != pPerson->m_nStartTime) {}
printf("Reader %d is Requesting ...\n",pPerson->m_nID);
// wait for the write request while(g_NumOfWriteRequest != 0) {}
WaitForSingleObject(g_hReadSemaphore,INFINITE); if(g_NumOfReading ==0) { WaitForSingleObject(g_hWriteSemaphore,INFINITE); } g_NumOfReading++; ReleaseSemaphore(g_hReadSemaphore,1,NULL); // modify the reader's real start time pPerson->m_nStartTime = g_CurrentTime;
printf("Reader %d is Reading the Shared Buffer...\n",pPerson->m_nID); while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime) { // .. perform read operations } printf("Reader %d is Exit...\n",pPerson->m_nID);
WaitForSingleObject(g_hReadSemaphore,INFINITE); g_NumOfReading--; if(g_NumOfReading == 0) { ReleaseSemaphore(g_hWriteSemaphore,1,NULL); }
ReleaseSemaphore(g_hReadSemaphore,1,NULL);
ExitThread(0);
return 0; }
DWORD WINAPI WriterProc(LPVOID lpParam) { Person *pPerson = (Person*)lpParam;
// wait for the start time while(g_CurrentTime != pPerson->m_nStartTime) {}
printf("Writer %d is Requesting ...\n",pPerson->m_nID); g_NumOfWriteRequest++; WaitForSingleObject(g_hWriteSemaphore,INFINITE); // modify the writer's real start time pPerson->m_nStartTime = g_CurrentTime; printf("Writer %d is Writting the Shared Buffer...\n",pPerson->m_nID); while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime) { // .. perform write operations } printf("Writer %d is Exit...\n",pPerson->m_nID); g_NumOfWriteRequest--; ReleaseSemaphore(g_hWriteSemaphore,1,NULL);
ExitThread(0); return 0; }
bool CreateReader(int StartTime,int WorkTime,int ID) { DWORD dwThreadID; if(g_NumPerson >= MAX_PERSON) return false;
Person *pPerson = &g_Persons[g_NumPerson]; pPerson->m_nID = ID; pPerson->m_nStartTime = StartTime; pPerson->m_nWorkTime = WorkTime; pPerson->m_nType = READER;
g_NumPerson++;
// Create an New Thread pPerson->m_hThread = CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread == NULL) return false;
return true; }
bool CreateWriter(int StartTime,int WorkTime,int ID) { DWORD dwThreadID; if(g_NumPerson >= MAX_PERSON) return false;
Person *pPerson = &g_Persons[g_NumPerson]; pPerson->m_nID = ID; pPerson->m_nStartTime = StartTime; pPerson->m_nWorkTime = WorkTime; pPerson->m_nType = WRITER;
g_NumPerson++;
// Create an New Thread pPerson->m_hThread = CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread == NULL) return false;
return true; }

|