作業系統實驗,IPC(2): reader and writer, 讀者和寫者問題
阿新 • • 發佈:2019-01-27
1.首先,關於訊號量的問題請看上一篇部落格。
2.讀者和寫者問題分為讀者和寫者對等且二者都不能多人讀取,讀者和寫者對等但都可以讀者可以多人讀取,讀者優先並且讀者可以多人讀取。寫者優先但是讀者可以多人讀取。
3.如果是二者對等,不管是不是多人讀取,只需要一個互斥量就可以了。這裡要說明一點,它和生產者和消費者不一樣。生產者和消費者問題的共享資源是有數目的。但是這裡沒有。
4.如果要實現讀者可以多人,必須給讀者一個單獨的訊號量。把讀者的進入和離開分成兩個步驟。只要讀者進入,就釋放資源。這樣後面的就可以繼續進入。
5.要實行讀者優先,就可以給讀者計數,如果讀者的數目剛開始或者最後一個的情況考慮一下就可以了。
6.所以下面的讀者可以多人讀取並且讀者優先就使用了兩個訊號量。不過應該用反了。應該是讀者和寫者共享的那個是mutex,複製的時候也是mutex,這裡說一下。因為我不想改了,只是覺得寫反了。
7.如果寫者優先,就需要計數,類似於讀者。
8,寫者優先還有一個問題,就是如果現在寫者在用共享變數,但是後面排隊的有讀者和寫者,這個寫者便不釋放資源,直接讓寫一個寫者使用資源即可。如此以來,讀者就需要一個單獨的變數。如前面所說,來保持全部寫者之間的輪流。
9,這時候就剩最後一個問題就可以實現寫者優先了。就是在讀者控制資源的時候,有寫者和讀者排隊,先到的先使用。我們需要一個全域性訊號量來做。就是來排隊。
下面是讀者優先的程式碼
#include<windows.h> #include<fstream> #include<cstdlib> #include<iostream> #include <ctime> using namespace std; const int MaxThread=20; HANDLE hX; HANDLE hWsem; HANDLE thread[MaxThread]; int readcount; double totaltime; void WRITEUNIT(int iProcess) { printf("%dth writer begins to write.\n",iProcess); Sleep((DWORD)(6000)); printf("End of %dth writer for writing.\n",iProcess); } void READUNIT(int iProcess) { printf("%dth reader begins to read.\n",iProcess); Sleep((DWORD)(3000)); printf("End of %dth reader for reading.\n",iProcess); } DWORD WINAPI reader(LPVOID lpVoid) { int iProcess = *(int*)lpVoid; //Sleep((DWORD)(3000)); DWORD wait_for=WaitForSingleObject(hX,INFINITE); printf("%dth reader requres reading.\n",iProcess); readcount++; if(readcount==1)WaitForSingleObject(hWsem,INFINITE); ReleaseMutex(hX); READUNIT(iProcess); wait_for=WaitForSingleObject(hX,INFINITE); readcount--; if(readcount==0) ReleaseSemaphore(hWsem,1,0); ReleaseMutex(hX); //use-data-read(); return iProcess; } DWORD WINAPI writer(LPVOID lpVoid) { int iProcess = *(int*)lpVoid; //Sleep((DWORD)(6000));//think-up-data printf("%d writer requres writing.\n",iProcess); DWORD wait_for=WaitForSingleObject(hWsem,INFINITE); WRITEUNIT(iProcess); ReleaseSemaphore(hWsem,1,0); return iProcess; } int main() { int threadNum; int threadcount; ifstream file; hX=CreateMutex(NULL, FALSE, NULL); hWsem=CreateSemaphore(NULL,1,1,NULL); //??????????????????? readcount=0; threadcount=0; totaltime=0; int readerThreadNum=0; int writerThreadNum=0; while(writerThreadNum<3&&readerThreadNum<6) { if(rand()%3==0) { printf("Creating %dth writer",writerThreadNum+1); writerThreadNum = writerThreadNum+1; thread[writerThreadNum] = CreateThread(NULL, 0,writer, &writerThreadNum,0,0); } if(rand()%2==0) { //h = CreateThread(NULL, 0, customer_thread, NULL, 0, NULL); printf("Creating %dth reader.\n",readerThreadNum+1); readerThreadNum=readerThreadNum+1; thread[readerThreadNum] = CreateThread(NULL, 0,reader, &readerThreadNum,0,0); } Sleep(2000); } Sleep((DWORD)(totaltime*1000)); system("pause"); return 1; }
下面是寫者優先的程式碼
#include<windows.h>
#include<fstream>
#include<cstdlib>
#include<iostream>
#include <ctime>
using namespace std;
const int MaxThread=20;
HANDLE queue;
HANDLE hWsem;
HANDLE hRsem;
HANDLE db;
HANDLE thread[MaxThread];
int readcount;
int writecount;
double totaltime;
//寫者的寫操作
void WRITEUNIT(int iProcess)
{
printf("%dth writer begins to write.\n",iProcess);
Sleep((DWORD)(6000));
printf("End of %dth writer for writing.\n",iProcess);
}
//讀者的讀操作
void READUNIT(int iProcess)
{
printf("%dth reader begins to read.\n",iProcess);
Sleep((DWORD)(3000));
printf("End of %dth reader for reading.\n",iProcess);
}
//讀者函式
DWORD WINAPI reader(LPVOID lpVoid)
{
int iProcess = *(int*)lpVoid;
//Sleep((DWORD)(3000));
//檢查是否是第一個讀者
WaitForSingleObject(queue,INFINITE);
DWORD wait_for=WaitForSingleObject(hRsem,INFINITE);
printf("%dth reader requres reading.\n",iProcess);
readcount++;
if(readcount==1)WaitForSingleObject(db,INFINITE);
ReleaseMutex(hRsem);
ReleaseMutex(queue);
//讀操作,沒有訊號量,因為不互斥
READUNIT(iProcess);
//檢查是不是最後一個讀者
wait_for=WaitForSingleObject(hRsem,INFINITE);
readcount--;
if(readcount==0)
ReleaseSemaphore(db,1,0);
ReleaseMutex(hRsem);
//use-data-read();
return iProcess;
}
//寫者函式
DWORD WINAPI writer(LPVOID lpVoid)
{
int iProcess = *(int*)lpVoid;
//Sleep((DWORD)(6000));//think-up-data
printf("%d writer requres writing.\n",iProcess);
//檢查是否是第一個寫者
WaitForSingleObject(hWsem,INFINITE);
writecount++;
if(writecount==1)WaitForSingleObject(queue,INFINITE);
ReleaseMutex(hWsem);
//寫操作
WaitForSingleObject(db,INFINITE);
WRITEUNIT(iProcess);
ReleaseSemaphore(db,1,0);
//WaitForSingleObject(hWsem,INFINITE);
//檢查是否是最後一個寫者
WaitForSingleObject(hWsem,INFINITE);
writecount--;
if(writecount==0)ReleaseMutex(queue);
ReleaseMutex(hWsem);
//ReleaseSemaphore(db,1,0);
return iProcess;
}
int main()
{
int threadNum;
int threadcount;
ifstream file;
queue=CreateMutex(NULL, FALSE, NULL);
hWsem=CreateMutex(NULL, FALSE, NULL);
hRsem=CreateMutex(NULL, FALSE, NULL);
db=CreateSemaphore(NULL,1,1,NULL);
//???????????????????
readcount=0;
writecount=0;
int readerThreadNum=0;
int writerThreadNum=0;
//保證寫者不超過3個或者讀者不超過6個
while(writerThreadNum<3&&readerThreadNum<6)
{
if(rand()%3==0)
{
printf("Creating %dth writer",writerThreadNum+1);
writerThreadNum = writerThreadNum+1;
thread[writerThreadNum] = CreateThread(NULL, 0,writer, &writerThreadNum,0,0);
}
if(rand()%2==0)
{
//h = CreateThread(NULL, 0, customer_thread, NULL, 0, NULL);
printf("Creating %dth reader.\n",readerThreadNum+1);
readerThreadNum=readerThreadNum+1;
thread[readerThreadNum] = CreateThread(NULL, 0,reader, &readerThreadNum,0,0);
}
Sleep(2000);
}
Sleep((DWORD)(totaltime*1000));
CloseHandle(db);
CloseHandle(queue);
CloseHandle(hRsem);
CloseHandle(hWsem);
//system("pause");
return 1;
}