1. 程式人生 > >作業系統實驗,IPC(2): reader and writer, 讀者和寫者問題

作業系統實驗,IPC(2): reader and writer, 讀者和寫者問題

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;
}