欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      讀者寫者實驗報告

      時間:2019-05-14 10:49:21下載本文作者:會員上傳
      簡介:寫寫幫文庫小編為你整理了多篇相關(guān)的《讀者寫者實驗報告》,但愿對你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫還可以找到更多《讀者寫者實驗報告》。

      第一篇:讀者寫者實驗報告

      操作系統(tǒng)原理 實驗報告

      實驗名稱:

      姓 名:學(xué) 號:班 級:指導(dǎo)老師:

      操作系統(tǒng) XXX xxxxxxxxxx xxx xxx

      一、實驗內(nèi)容

      在Windows2000環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含n個線程。用這n個線程來表示n個讀者或?qū)懻摺C總€線程按相應(yīng)測試數(shù)據(jù)文件(后面有介紹)的要求進行讀寫操作。用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者-寫者問題。讀者-寫者問題的讀寫操作限制(包括讀者優(yōu)先和寫者優(yōu)先): 1)寫-寫互斥,即不能有兩個寫者同時進行寫操作。

      2)讀-寫互斥,即不能同時有一個線程在讀,而另一個線程在寫。,3)讀-讀允許,即可以有一個或多個讀者在讀。

      讀者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一個讀者正在進行讀操作,則該讀者可直接開始讀操作。

      寫者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一寫者在等待訪問共享資源,則該讀者必須等到?jīng)]有寫者處于等待狀態(tài)后才能開始讀操作。運行結(jié)果顯示要求:要求在每個線程創(chuàng)建、發(fā)出讀寫操作申請、開始讀寫操作和結(jié)束讀寫操作時分別顯示一行提示信息,以確定所有處理都遵守相應(yīng)的讀寫操作限制。

      二、實驗?zāi)康?/p>

      在Windows2000環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含n個線程。用這n個線程來表示n個讀者或?qū)懻摺C總€線程按相應(yīng)測試數(shù)據(jù)文件(后面有介紹)的要求進行讀寫操作。用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者-寫者問題。

      三、實驗原理 1).讀者優(yōu)先

      讀者優(yōu)先指的是除非有寫者在寫文件,否則讀者不需要等待。所以可以用一個整型變量read_count記錄當(dāng)前的讀者數(shù)目,用于確定是否需要釋放正在等待的寫者線程(當(dāng)read_count=O時,表明所有的讀者讀完,需要釋放寫者等待隊列中的一個寫者)。每一個讀者開始讀文件時,必須修改read_count變量。因此需要一個互斥對象mutex來實現(xiàn)對全局變量read_count修改時的互斥。

      另外,為了實現(xiàn)寫-寫互斥,需要增加一個臨界區(qū)對象write。當(dāng)寫者發(fā)出寫請求時,必須申請臨界區(qū)對象的所有權(quán)。通過這種方法,也可以實現(xiàn)讀-寫互斥,當(dāng)read_count=l時(即第一個讀者到來時),讀者線程也必須申請臨界區(qū)對象的所有權(quán)。

      當(dāng)讀者擁有臨界區(qū)的所有權(quán)時,寫者阻塞在臨界區(qū)對象write上。當(dāng)寫者擁有臨界區(qū)的所有權(quán)時,第一個讀者判斷完 “read_count==1”后阻塞在write上,其余的讀者由于等待對read_count的判斷,阻塞在mutex上。

      2).寫者優(yōu)先

      寫者優(yōu)先與讀者優(yōu)先類似;不同之處在于一旦一個寫者到來,它應(yīng)該盡快對文件進行寫操作,如果有一個寫者在等待,則新到來的讀者不允許進行讀操作。為此應(yīng)當(dāng)添加一個整型變量write_count,用于記錄正在等待的寫者的數(shù)目,當(dāng)write_count=O時,才可以釋放等待的讀者線程隊列。

      為了對全局變量write_count實現(xiàn)互斥,必須增加一個互斥對象mutex3。為了實現(xiàn)寫者優(yōu)先,應(yīng)當(dāng)添加一個臨界區(qū)對象read,當(dāng)有寫者在寫文件或等 待時,讀者必須阻塞在read上?!?/p>

      讀者線程除了要對全局變量read_count實現(xiàn)操作上的互斥外,還必須有一個互斥對象對阻塞,read這一過程實現(xiàn)互斥。這兩個互斥對象分別命名為mutex1和mutex2。

      四、實驗過程

      在Windows2000環(huán)境下,創(chuàng)建一個控制臺進程。用VC++實現(xiàn)。

      讀者優(yōu)先指的是除非有寫者在寫文件,否則讀者不需要等待。所以可以用一個整型變量read_count記錄當(dāng)前的讀者數(shù)目,用于確定是否需要釋放正在等待的寫者線程(當(dāng)read_count=O時,表明所有的讀者讀完,需要釋放寫者等待隊列中的一個寫者)。每一個讀者開始讀文件時,必須修改read_count變量。因此需要一個互斥對象mutex來實現(xiàn)對全局變量read_count修改時的互斥。

      另外,為了實現(xiàn)寫-寫互斥,需要增加一個臨界區(qū)對象write。當(dāng)寫者發(fā)出寫請求時,必須申請臨界區(qū)對象的所有權(quán)。通過這種方法,也可以實現(xiàn)讀-寫互斥,當(dāng)read_count=l時(即第一個讀者到來時),讀者線程也必須申請臨界區(qū)對象的所有權(quán)。

      當(dāng)讀者擁有臨界區(qū)的所有權(quán)時,寫者阻塞在臨界區(qū)對象write上。當(dāng)寫者擁有臨界區(qū)的所有權(quán)時,第一個讀者判斷完 “read_count==1”后阻塞在write上,其余的讀者由于等待對read_count的判斷,阻塞在mutex上。

      寫者優(yōu)先與讀者優(yōu)先類似;不同之處在于一旦一個寫者到來,它應(yīng)該盡快對文件進行寫操作,如果有一個寫者在等待,則新到來的讀者不允許進行讀操作。為此應(yīng)當(dāng)添加一個整型變量write_count,用于記錄正在等待的寫者的數(shù)目,當(dāng)write_count=O時,才可以釋放等待的讀者線程隊列。

      為了對全局變量write_count實現(xiàn)互斥,必須增加一個互斥對象mutex3。為了實現(xiàn)寫者優(yōu)先,應(yīng)當(dāng)添加一個臨界區(qū)對象read,當(dāng)有寫者在寫文件或等 待時,讀者必須阻塞在read上?!?/p>

      讀者線程除了要對全局變量read_count實現(xiàn)操作上的互斥外,還必須有一個互斥對象對阻塞,read這一過程實現(xiàn)互斥。這兩個互斥對象分別命名為mutex1和mutex2。結(jié)構(gòu):

      頭文件 定義全局變量

      RP_ReaderThread()讀者優(yōu)先---讀者線程 RP_WriterThread()讀者優(yōu)先---寫者線程 ReaderPriority()讀者優(yōu)先處理函數(shù) WP_ReaderThrea()寫者優(yōu)先---讀者線程 WP_WriterThread()寫者優(yōu)先---寫者線程 WriterPriority()寫者優(yōu)先處理函數(shù)

      主函數(shù):包含對dat文件的讀取以及函數(shù)的調(diào)用。代碼:附錄

      五、實驗結(jié)果

      界面:

      測試數(shù)據(jù): 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 結(jié)果 讀者優(yōu)先

      寫者優(yōu)先

      六、實驗心得體會

      通過對讀者寫者問題的編程,對線程有了更深的了解,希望在后面的學(xué)習(xí)中懂得更多。

      七、參考文獻

      老師提供的資料,以及互聯(lián)網(wǎng)查閱。

      八、附錄

      #include “windows.h” #include #include #include #include #include #include #include “winbase.h”

      #define READER 'R' // 讀者 #define WRITER 'W' // 寫者

      #define INTE_PER_SEC 1000 // 每秒時鐘中斷的數(shù)目 #define MAX_THREAD_NUM 64 // 最大線程數(shù) int nReaderCnt = 0;// 讀者計數(shù) int nWriterCnt = 0;// 寫者計數(shù)

      HANDLE hWrite = ::CreateSemaphore(NULL, 1, 1, NULL);// 寫開始信號

      HANDLE hRead = ::CreateSemaphore(NULL, 1, 1, NULL);// 讀開始信號

      HANDLE hRCMutex = ::CreateMutex(NULL, FALSE, NULL);HANDLE hWCMutex = ::CreateMutex(NULL, FALSE, NULL);HANDLE hReadMutex = ::CreateMutex(NULL, FALSE, NULL);// 從測試數(shù)據(jù)文件中獲取的線程信息 struct ThreadInfo { ThreadInfo(){ nSerialNo = 0;cType = '^';dDelayTime = 0.0;dOpeTime = 0.0;} int nSerialNo;// 線程序號 char cType;// 線程類別 double dDelayTime;// 線程延遲時間 double dOpeTime;// 線程讀寫操作時間 };// 讀者優(yōu)先---讀者線程 // P:讀者線程信息

      void RP_ReaderThread(void *p){

      int nSerialNo =((ThreadInfo*)(p))->nSerialNo;//從文件中讀取 線程序號 DWORD dwReadTime

      =

      (DWORD)(((ThreadInfo*)(p))->dOpeTime

      * INTE_PER_SEC);DWORD dwDelay

      =

      (DWORD)(((ThreadInfo*)(p))->dDelayTime

      * INTE_PER_SEC);Sleep(dwDelay);printf(“Reader thread %d sents the reading require.n”,nSerialNo);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt++;if(nReaderCnt == 1){ WaitForSingleObject(hWrite, INFINITE);} ReleaseMutex(hRCMutex);printf(“Reader thread %d begins to read file.n”, nSerialNo);Sleep(dwReadTime);printf(“Reader thread %d finished reading file.n”, nSerialNo);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt--;if(nReaderCnt == 0){ ReleaseSemaphore(hWrite, 1, NULL);} ReleaseMutex(hRCMutex);} // 讀者優(yōu)先---寫者線程 // P:寫者線程信息

      void RP_WriterThread(void *p){

      int nSerialNo =((ThreadInfo*)(p))->nSerialNo;// 從參數(shù)中獲得信息

      DWORD dwWriteTime =(DWORD)(((ThreadInfo*)(p))->dOpeTime * INTE_PER_SEC);DWORD dwDelay

      =

      (DWORD)(((ThreadInfo*)(p))->dDelayTime

      * INTE_PER_SEC);Sleep(dwDelay);printf(“Write thread %d sents the writing require.n”,nSerialNo);WaitForSingleObject(hWrite, INFINITE);printf(“Writer thread %d begins to write to the file.n”, nSerialNo);Sleep(dwWriteTime);printf(“Write thread %d finished writing to the file.n”, nSerialNo);

      ReleaseSemaphore(hWrite, 1, NULL);} // 讀者優(yōu)先處理函數(shù) // file:文件名

      void ReaderPriority(char *file){ int nThreadCnt = 0;DWORD dwThreadID = 0;nReaderCnt = 0;// 初始化讀寫者計數(shù) HANDLE hThreads[MAX_THREAD_NUM];ThreadInfo oThreadInfo[MAX_THREAD_NUM];ifstream inFile;inFile.open(file);printf(“Reader Priority:nn”);while(inFile){ // 讀入每一個讀者,寫者的信息

      inFile>>oThreadInfo[nThreadCnt].nSerialNo;inFile>>oThreadInfo[nThreadCnt].cType;inFile>>oThreadInfo[nThreadCnt].dDelayTime;inFile>>oThreadInfo[nThreadCnt].dOpeTime;if('^'!= oThreadInfo[nThreadCnt].cType){ nThreadCnt++;} inFile.get();} // 創(chuàng)建線程

      for(int i = 0;i< nThreadCnt;i++){ if((oThreadInfo[i].cType==READER)||(oThreadInfo[i].cType == 'r')){ hThreads[i]

      =

      CreateThread(NULL,(LPTHREAD_START_ROUTINE)(RP_ReaderThread), // 創(chuàng)建讀者進程 &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID);} else { hThreads[i]

      =

      CreateThread(0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),// 創(chuàng)建寫線程 &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID);} }

      for(i = 0;i< nThreadCnt;i++){

      0,NULL, ResumeThread(hThreads[i]);} WaitForMultipleObjects(nThreadCnt, hThreads, TRUE, INFINITE);printf(“All reader and writer have finished operating.n”);} // 寫者優(yōu)先---讀者線程 // P:讀者線程信息

      void WP_ReaderThread(void *p){ int nSerialNo =((ThreadInfo*)(p))->nSerialNo;// 從參數(shù)中得到信息 DWORD dwReadTime

      =

      (DWORD)(((ThreadInfo*)(p))->dOpeTime

      * INTE_PER_SEC);DWORD dwDelay

      =

      (DWORD)(((ThreadInfo*)(p))->dDelayTime

      * INTE_PER_SEC);Sleep(dwDelay);printf(“Reader thread %d sents the reading require.n”,nSerialNo);WaitForSingleObject(hReadMutex, INFINITE);WaitForSingleObject(hRead, INFINITE);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt++;if(nReaderCnt==1){ WaitForSingleObject(hWrite, INFINITE);} ReleaseMutex(hRCMutex);ReleaseSemaphore(hRead, 1, NULL);ReleaseMutex(hReadMutex);printf(“Reader thread %d begins to read file.n”, nSerialNo);Sleep(dwReadTime);printf(“Reader thread %d finished reading file.n”, nSerialNo);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt--;if(nReaderCnt == 0){ ReleaseSemaphore(hWrite, 1, NULL);} ReleaseMutex(hRCMutex);} // 寫者優(yōu)先---寫者線程 // P:寫者線程信息

      void WP_WriterThread(void *p){ int nSerialNo =((ThreadInfo*)(p))->nSerialNo;DWORD dwWriteTime =(DWORD)(((ThreadInfo*)(p))->dOpeTime * INTE_PER_SEC);DWORD dwDelay

      =

      (DWORD)(((ThreadInfo*)(p))->dDelayTime

      * INTE_PER_SEC);Sleep(dwDelay);printf(“Writer thread %d sents the writing require.n”,nSerialNo);WaitForSingleObject(hWCMutex, INFINITE);nWriterCnt++;if(nWriterCnt == 1){ WaitForSingleObject(hRead, INFINITE);} ReleaseMutex(hWCMutex);WaitForSingleObject(hWrite, INFINITE);printf(“Writer thread %d begins to write to the file.n”, nSerialNo);Sleep(dwWriteTime);printf(“Writer thread %d finished writing to the file.n”, nSerialNo);ReleaseSemaphore(hWrite, 1, NULL);WaitForSingleObject(hWCMutex, INFINITE);nWriterCnt--;if(nWriterCnt == 0){ ReleaseSemaphore(hRead, 1, NULL);} ReleaseMutex(hWCMutex);} // 寫者優(yōu)先處理函數(shù) // file:文件名

      void WriterPriority(char * file){ int nThreadCnt = 0;DWORD dwThreadID;

      HANDLE hThreads[MAX_THREAD_NUM];ThreadInfo oThreadInfo[MAX_THREAD_NUM];

      nReaderCnt=0;nWriterCnt=0;

      ifstream inFile;inFile.open(file);printf(“Writer priority:nn”);while(inFile){ inFile>>oThreadInfo[nThreadCnt].nSerialNo;inFile>>oThreadInfo[nThreadCnt].cType;inFile>>oThreadInfo[nThreadCnt].dDelayTime;inFile>>oThreadInfo[nThreadCnt].dOpeTime;if('^'!= oThreadInfo[nThreadCnt].cType){ nThreadCnt++;} inFile.get();}

      for(int i = 0;i < nThreadCnt;i++)// 創(chuàng)建線程 { if((oThreadInfo[i].cType == READER)||(oThreadInfo[i].cType == 'r')){ hThreads[i]

      =

      CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_ReaderThread), //創(chuàng)建讀者進程 &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID);} else { hThreads[i]

      =

      CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_WriterThread), &oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);} } for(i = 0;i< nThreadCnt;i++){ ResumeThread(hThreads[i]);} WaitForMultipleObjects(nThreadCnt, hThreads, TRUE, INFINITE);

      printf(“All reader and writer have finished operating.n”);} int main(int argc,char *argv[]){ char ch;while(true){ printf(“*************************************n”);printf(“ 1.Reader Priorityn”);printf(“ 2.Writer Priorityn”);printf(“ 3.Exit to Windowsn”);printf(“*************************************n”);printf(“Enter your choice1,2,3: ”);do{ ch=(char)_getch();}while(ch!='1'&&ch!='2'&&ch!='3');system(“cls”);if(ch=='3')return 0;else if(ch=='1')ReaderPriority(“thread.dat”);else WriterPriority(“thread.dat”);printf(“nPress Any Key to Coutinue:”);_getch();system(“cls”);} return 0;}

      第二篇:操作系統(tǒng)讀者寫者實驗報告

      目錄

      一 設(shè)計概述 ……………………………………………………2

      二 設(shè)計目的與內(nèi)容 ……………………………………………3

      三 設(shè)計分析 ……………………………………………………4

      四 程序?qū)崿F(xiàn) ……………………………………………………5

      五 程序調(diào)試 ……………………………………………………6

      六 結(jié)果分析和討論 ……………………………………………6

      七 心得體會 ……………………………………………………7

      八 源代碼 ………………………………………………………7

      一 設(shè)計概述

      所謂讀者寫者問題,是指保證一個writer進程必須與其他進程互斥地訪問共享對象的同步問題。

      讀者寫者問題可以這樣的描述,有一群寫者和一群讀者,寫者在寫同一本書,讀者也在讀這本書,多個讀者可以同時讀這本書,但是,只能有一個寫者在寫書,并且,讀者必寫者優(yōu)先,也就是說,讀者和寫者同時提出請求時,讀者優(yōu)先。當(dāng)讀者提出請求時需要有一個互斥操作,另外,需要有一個信號量S來當(dāng)前是否可操作。

      信號量機制是支持多道程序的并發(fā)操作系統(tǒng)設(shè)計中解決資源共享時進程間的同步與互斥的重要機制,而讀者寫者問題則是這一機制的一個經(jīng)典范例。

      與記錄型信號量解決讀者—寫者問題不同,信號量機制它增加了一個限制,即最多允許RN個讀者同時讀。為此,又引入了一個信號量L,并賦予初值為RN,通過執(zhí)行wait(L,1,1)操作,來控制讀者的數(shù)目,每當(dāng)有一個讀者進入時,就要執(zhí)行wait(L,1,1)操作,使L的值減1。當(dāng)有RN個讀者進入讀后,L便減為0,第RN+1 個讀者要進入讀時,必然會因wait(L,1,1)操作失敗而堵塞。對利用信號量來解決讀者—寫者問題的描述如下: Var RN integer;L,mx:semaphore: =RN,1; Begin Parbegin Reader :begin Repeat Swait(L,1,1);Swait(mx,1,0);.Perform reader operation;Ssignal(L,1);Until false;End Writer :begin Repeat Swait(mx ,1,1,l,RN,0);Perform writer operation;Ssignal(mx,1);Until false;End Parend End 其中,Swait(mx,1,0)語句起著開關(guān)作用,只要無Writer進程進入些,mx=1,reader進程就都可以進入讀。但是要一旦有Writer進程進入寫時,其MX=0,則任何reader進程就都無法進入讀。Swait(mx ,1,1,l,RN,0)語句表示僅當(dāng)既無Write進程在寫(mx=1),又無reader進程在讀(L=RN)時,writer進程才能進入臨界區(qū)寫。

      本設(shè)計方案就是通過利用記錄型信號量對讀者寫者問題的解決過程進行模擬演示,形象地闡述記錄型信號量機制的工作原理。

      二 設(shè)計目的與內(nèi)容

      一 實驗?zāi)康?/p>

      l.用信號量來實現(xiàn)讀者寫者問題。

      2.理解和運用信號量、PV原語、進程間的同步互斥關(guān)系等基本知識。

      二、二 實驗內(nèi)容

      讀者寫者問題的定義如下:有一個許多進程共享的數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)可以是一個文件或者主存的一塊空間;有一些只讀取這個數(shù)據(jù)區(qū)的進程(Reader)和一些只往數(shù)據(jù)區(qū)寫數(shù)據(jù)的進程(Writer),此外還需要滿足以下條件:

      (1)任意多個讀進程可以同時讀這個文件;(2)一次只有一個寫進程可以往文件中寫;

      (3)如果一個寫進程正在進行操作,禁止任何讀進程度文件。我們需要分兩種情況實現(xiàn)該問題:

      讀優(yōu)先:要求指一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。

      寫優(yōu)先:一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作后才開始讀操作。

      三設(shè)計分析

      在Windows 7 環(huán)境下,創(chuàng)建一個包含n 個線程的控制臺進程。用這n 個線程來表示n個讀者或?qū)懻摺C總€線程按相應(yīng)測試數(shù)據(jù)文件的要求,進行讀寫操作。請用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者-寫者問題。

      讀者-寫者問題的讀寫操作限制:

      讀者-寫者的讀寫限制(包括讀者優(yōu)先和寫者優(yōu)先)1)寫-寫互斥,即不能有兩個寫者同時進行寫操作

      2)讀-寫互斥,即不能同時有一個讀者在讀,同時卻有一個寫者在寫 3)讀讀允許,即可以有2個以上的讀者同時讀

      將所有的讀者和所有的寫者分別放進兩個等待隊列中,當(dāng)讀允許時就讓讀者隊列釋放一個或多個讀者,當(dāng)寫允許時,釋放第一個寫者操作。讀者寫者問題的定義如下:有一個許多進程共享的數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)可以是一個文件或者主存的一塊空間;有一些只讀取這個數(shù)據(jù)區(qū)的進程(Reader)和一些只往數(shù)據(jù)區(qū)寫數(shù)據(jù)的進程(Writer),此外還需要滿足以下條件:1)任意多個讀進程可以同時讀這個文件;2)一次只有一個寫進程可以往文件中寫;3)如果一個寫進程正在進行操作,禁止任何讀進程度文件。我們需要分兩種情況實現(xiàn)該問題:

      讀優(yōu)先:要求指一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。寫優(yōu)先:一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作后才開始讀操作。

      四 程序?qū)崿F(xiàn)

      程序由兩部分組成:

      1。讀者-寫者模塊:包括系統(tǒng)調(diào)用接口,讀者-寫者活動描述主程序。系統(tǒng)接口主要功能是通過管道向父進程發(fā)送系統(tǒng)調(diào)用命令,并讀取父進程送來的返回值。

      讀者-寫者活動程序根據(jù)臨界資源的共享,互斥原則編制,具體見源程序。2。主控模塊:主控模塊實現(xiàn)系統(tǒng)初始化系統(tǒng)調(diào)用命令接收與解釋執(zhí)行,系統(tǒng)調(diào)用功能的實現(xiàn)(包括信號量機制),及讀者-寫者活動過程記錄與顯示。

      初始化系統(tǒng)環(huán)境 建立通信管道

      啟動讀者-寫者進程 接收系統(tǒng)調(diào)用命令 解釋執(zhí)行

      系統(tǒng)初始化模塊 管道建立模塊 進程啟動模塊 命令解釋模塊 Wait()Signal()Wakeup()Block()

      五 程序調(diào)試

      測試數(shù)據(jù)文件格式: 測試數(shù)據(jù)文件包括n 行測試數(shù)據(jù),分別描述創(chuàng)建的n 個線程是讀者還是寫者,以及讀寫操作的開始時間和持續(xù)時間。每行測試數(shù)據(jù)包括四個字段,各字段間用空格分隔。第一字段為一個正整數(shù),表示線程序號。第二字段表示相應(yīng)線程角色,R 表示讀者是,W 表示寫者。第三字段為一個正數(shù),表示讀寫操作的開始時間。線程創(chuàng)建后,延時相應(yīng)時間(單位為秒)后發(fā)出對共享資源的讀寫申請。第四字段為一個正數(shù),表示讀寫操作的持續(xù)時間。當(dāng)線程讀寫申請成功后,開始對共享資源的讀寫操作,該操作持續(xù)相應(yīng)時間后結(jié)束,并釋放共享資源。

      六 結(jié)果分析和討論

      在讀者寫者同時在隊列中等待申請資時,讀者優(yōu)先調(diào)用資源。而且如果一個讀者申請進行讀操作時已有另一讀者正在進行讀操作,則該讀者可直接開始讀操作,即讀讀允許。

      進程1是R操作,在時間3時進入隊列,運行時間是5,在它進入時沒有進程占用資源,它既占用資源;知道它釋放資源,等候的進程有3,4,5;

      進程2是W操作,在時間16時進入隊列,運行時間是5,在它進入時進程4占用資源,它等待資源,當(dāng)4釋放時占用資源;

      進程3是R操作,在時間5時進入隊列,運行時間是2,在它進入時進程1占用資源,它等待資源,當(dāng)進程1釋放資源后,由于讀者優(yōu)先,進程3,5同時調(diào) 運資源;

      進程4是R操作,在時間6時進入隊列,運行時間是5,在它進入時進程1占用資源,它等待資源,當(dāng)進程1釋放資源后,由于讀者優(yōu)先,進程3,5占用資源,它依然等待,直到進程3,5都結(jié)束;

      進程5是W操作,在時間4時進入隊列,運行時間是3, 在它進入時進程1占用資源,它等待資源,當(dāng)進程1釋放資源后,由于讀者優(yōu)先,進程3,5同時調(diào)運資源;

      七 心得體會

      這一次課程設(shè)計,讓我體會很深刻。讀者-寫者問題經(jīng)典的線程同步問題的一個模型。經(jīng)過讀者寫者問題的編寫,我對同步機構(gòu)應(yīng)用有了深入的了解。懂得了運用信號量實現(xiàn)進程間的互斥。實現(xiàn)了不讓共享資源同時修改。用信號量上的原語操作使臨界段問題的解決比較簡單明了了。讀者寫者問題的編寫,花的時間很多,也學(xué)到很多東西。了解支持多道程序的并發(fā)操作系統(tǒng)設(shè)計中解決資源共享時進程間的同步與互斥的信號量機制。幾天的試驗,雖然難度有點大,但只要自己花時間去學(xué)習(xí),還是會攻克困難的。

      總之,每一次課程設(shè)計不僅是我們學(xué)習(xí)的好機會,而且是我們鍛煉實際動手能力的平臺,雖然有難度的東西總會讓人很抵觸,比如在課設(shè)過程中有很多郁悶的時候,一個小小的錯誤一不小心就花去了自己一上午的時間,所以在這個過程中能夠磨練人的意志與耐心,最后感謝老師的指導(dǎo)與監(jiān)督。

      八 源代碼

      #include #include #include #include #include #include #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;//基本時間片數(shù) int g_PersonLists[] = {//進程隊列 1, R, 3, 5, 2, W, 4, 5, 3, R, 5, 2, 4, R, 6, 5, 5, W, 5.1, 3, END,};int g_NumOfReading = 0;int g_NumOfWriteRequest = 0;//申請寫進程的個數(shù) HANDLE g_hReadSemaphore;//讀者信號 HANDLE g_hWriteSemaphore;//寫者信號 bool finished = false;//所有的讀完成 //bool wfinished = false;//所有的寫完成 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);//創(chuàng)建信號燈,當(dāng)前可用的資源數(shù)為1,最大為100 g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL);//創(chuàng)建信號燈,當(dāng)前可用的資源數(shù)為1,最大為100 CreatePersonList(g_PersonLists);// Create All the reader and writers printf(“Created all the reader and writern...n”);g_CurrentTime = 0;while(true){ g_CurrentTime++;Sleep(300);// 300 ms printf(“CurrentTime = %dn”,g_CurrentTime);if(finished)return 0;} // 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]);//351,w452,523,654 break;case W: Ret = CreateWriter(pList[2],pList[3],pList[0]);break;} if(!Ret)printf(“Create Person %d is wrongn”,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);printf(“nn************************************************n”);// wait for the write request WaitForSingleObject(g_hReadSemaphore,INFINITE);if(g_NumOfReading ==0){ WaitForSingleObject(g_hWriteSemaphore,INFINITE);} g_NumOfReading++;ReleaseSemaphore(g_hReadSemaphore,1,NULL);pPerson->m_nStartTime = g_CurrentTime;printf(“Reader %d is Reading the Shared Buffer...n”,pPerson->m_nID);printf(“nn************************************************n”);while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime){} printf(“Reader %d is Exit...n”,pPerson->m_nID);printf(“nn************************************************n”);WaitForSingleObject(g_hReadSemaphore,INFINITE);g_NumOfReading--;if(g_NumOfReading == 0){ReleaseSemaphore(g_hWriteSemaphore,1,NULL);//此時沒有讀者,可以寫 } ReleaseSemaphore(g_hReadSemaphore,1,NULL);if(pPerson->m_nID == 4)finished = true;//所有的讀寫完成 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);printf(“nn************************************************n”);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){} printf(“Writer %d is Exit...n”,pPerson->m_nID);printf(“nn************************************************n”);//g_NumOfWriteRequest--;ReleaseSemaphore(g_hWriteSemaphore,1,NULL);if(pPerson->m_nID == 4)finished = true;//所有的讀寫完成 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;}

      第三篇:讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)

      4.1實驗二:讀者寫者問題 4.1.1實驗要求

      在Windows 環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含n個線程。用這n個線程來表示n個讀者或?qū)懻摺C總€線程按相應(yīng)測試數(shù)據(jù)文件(后面有介紹)的要求進行讀寫操作。用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者-寫者問題。

      讀者-寫者問題的讀寫操作限制(包括讀者優(yōu)先和寫者優(yōu)先): 1)寫-寫互斥,即不能有兩個寫者同時進行寫操作。

      2)讀-寫互斥,即不能同時有一個線程在讀,而另一個線程在寫。3)讀-讀允許,即可以有一個或多個讀者在讀。

      讀者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一個讀者正在進行讀操作,則該讀者可直接開始讀操作。

      寫者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一寫者在等待訪問共享資源,則該讀者必須等到?jīng)]有寫者處于等待狀態(tài)才能開始讀操作。

      運行結(jié)果顯示要求:要求在每個線程創(chuàng)建、發(fā)出讀寫操作申請、開始讀寫操作和結(jié)果讀寫操作時分別顯示一行提示信息,以確定所有處理都遵守相應(yīng)的讀寫操作限制。4.1.2測試數(shù)據(jù)文件格式

      測試數(shù)據(jù)文件包括n行測試數(shù)據(jù),分別描述創(chuàng)建的n個線程是讀者還是寫者,以及讀寫操作的開始時間和持續(xù)時間。每行測試數(shù)據(jù)包括四個字段,各個字段間用空格分隔。第一字段為一個正整數(shù),表示線程序號。第二字段表示相應(yīng)線程角色,R表示讀者,W表示寫者。第三字段為一個正數(shù),表示讀寫操作的開始時間:線程創(chuàng)建后,延遲相應(yīng)時間(單位為秒)后發(fā)出對共享資源的讀寫申請。第四字段為一個正數(shù),表示讀寫操作的持續(xù)時間。當(dāng)線程讀寫申請成功后,開始對共享資源的讀寫操作,該操作持續(xù)相應(yīng)時間后結(jié)束,并釋放共享資源。

      下面是一個測試數(shù)據(jù)文件的例子: 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 注意:

      在創(chuàng)建數(shù)據(jù)文件時,由于涉及到文件格式問題,最好在記事本中手工逐個鍵入數(shù)據(jù),而不要拷貝粘貼數(shù)據(jù),否則,本示例程序運行時可能會出現(xiàn)不可預(yù)知的錯誤。4.1.3實習(xí)分析

      可以將所有讀者和所有寫者分別存于一個讀者等待隊列和一個寫者等待隊列中,每當(dāng)讀允許時,就從讀者隊列中釋放一個或多個讀者線程進行讀操作;每當(dāng)寫允許時,就從寫者隊列中釋放一個寫者進行寫操作。

      1.讀者優(yōu)先

      讀者優(yōu)先指的是除非有寫者在寫文件,否則讀者不需要等待。所以可以用一個整型變量read-count記錄當(dāng)前的讀者數(shù)目,用于確定 是否需要釋放正在等待的寫者線程(當(dāng)read-count=0時,表明所有的讀者讀完,需要釋放寫者等待隊列中的一個寫者)。每一個讀者開始讀文件時,必須修改read-count變量。因此需要一個互斥對象mutex來實現(xiàn)對全局變量read-count修改時的互斥。

      另外,為了實現(xiàn)寫-寫互斥,需要增加一個臨界區(qū)對象write。當(dāng)寫者發(fā)出寫請求時,必須申請臨界區(qū)對象的所有權(quán)。通過這種方法,也可以實現(xiàn)讀-寫互斥,當(dāng)read-count=1時(即第一個讀者到來時),讀者線程也必須申請臨界區(qū)對象的所有權(quán)。當(dāng)讀者擁有臨界區(qū)的所有權(quán)時,寫者阻塞在臨界區(qū)對象write上。當(dāng)寫者擁有臨界區(qū)的所有權(quán)時,第一個讀者判斷完“read-count==1”后阻塞在write上,其余的讀者由于等待對read-count的判斷,阻塞在mutex上。

      2.寫者優(yōu)先

      寫者優(yōu)先與讀者優(yōu)先類似。不同之處在于一旦一個寫者到來,它應(yīng)該盡快對文件進行寫操作,如果有一個寫者在等待,則新到來的讀者不允許進行讀操作。為此應(yīng)當(dāng)添加一個整型變量write-count,用于記錄正在等待的寫者數(shù)目,當(dāng)write-count=0時,才可以釋放等待的讀者線程隊列。

      為了對全局變量write-count實現(xiàn)互斥,必須增加一個互斥對象mutex3。

      為了實現(xiàn)寫者優(yōu)先,應(yīng)當(dāng)添加一個臨界區(qū)對象read,當(dāng)有寫者在寫文件或等待時,讀者必須阻塞在read上。

      讀者線程除了要對全局變量read-count實現(xiàn)操作上的互斥外,還必須有一個互斥對象對阻塞read這一過程實現(xiàn)互斥。這兩個互斥對象分別命名為mutex1和mutex2。4.1.4相關(guān)API函數(shù)說明

      1.CreateThread 函數(shù)功能:

      該函數(shù)創(chuàng)建一個在調(diào)用進程的地址空間中執(zhí)行的線程。函數(shù)原型:

      HANDLE CreateThread(LPSECURITY-ATTRIBUTES lpThreadAttributes, DWORD dwStackSize,LPTHREAD-START-TOUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LLPDWORD lpThreadId);參數(shù):

      ·lpThreadAttributes:指向一個SECURITY-ATTRIBUTES結(jié)構(gòu),該結(jié)構(gòu)決定了返回的句柄是否可被子進程繼承。若lpThreadAttributes為NULL,則句柄不能被繼承。在Windows NT中該結(jié)構(gòu)的lpSwcurityDescriptor成員定義了新進程的安全性描述符。若lpThreadAttributes為NULL,則線程獲得一個默認的安全性描述符?!wStackSize:定義原始堆棧提交時的大?。ò醋止?jié)計)。系統(tǒng)將該值舍入為最近的頁。若該值為0,或小于默認時提交的大小,默認情況是使用與調(diào)用線程同樣的大小。更多的信息,請看Thread Stack Size。

      ·lpStartAddress:指向一個LPTHREAD-START-TOUTINE類型的應(yīng)用定義的函數(shù),該線程執(zhí)行此函數(shù)。該指針還表示遠程進程中線程的起始地址。該函數(shù)必須存在于遠程進程中。

      ·lpParameter:定義一個傳遞給該進程的32位值。

      ·dwCreationFlags:定義控制進程創(chuàng)建的附加標志。若定義CREATE-SUSPENDED標志,線程創(chuàng)建時處于掛起狀態(tài),并且直到ResumeThread函數(shù)調(diào)用時才能運行。若該值為0,則該線程在創(chuàng)建后立即執(zhí)行。

      ·lpThreadId:指向一個32位值,它接收該線程的標識符。返回值:

      若函數(shù)調(diào)用成功,返回值為新線程的句柄;若函數(shù)調(diào)用失敗,返回值為NULL。備注:

      新線程的句柄創(chuàng)建時設(shè)為THREAD-ALL-ACCESS訪問權(quán)限。若未提供安全性描述符,則該句柄可被任何要求一個線程對象句柄的函數(shù)所使用。若提供了安全性描述符,則以后使用該句柄時,將在授權(quán)訪問以前執(zhí)行訪問檢查。若訪問檢查被拒絕訪問,則請求進程不能使用該句柄獲得對該線程的訪問。線程從lpStartAddress參數(shù)定義的函數(shù)處開始執(zhí)行。若該函數(shù)返回,系統(tǒng)將默認地認為以調(diào)用ExitThread函數(shù)的方法終止該線程。使用GetExitCodeThread 函數(shù)來獲得線程的返回值。

      線程創(chuàng)建時擁有THREAD-PRIORITY-NORMAL優(yōu)先權(quán)。使用GetThreadPriority和SetThreadPriority函數(shù)可以獲得和設(shè)置線程的優(yōu)先權(quán)值。

      一個線程終止時,該線程對象被設(shè)為發(fā)信號狀態(tài),以滿足在該對象上等待的所有進程。一個線程對象始終存在于系統(tǒng)中,直到該線程終止,且它所有的句柄都已通過調(diào)用CloseHandle函數(shù)關(guān)閉。

      2.ExitThread 函數(shù)功能:

      該函數(shù)結(jié)束一個線程。函數(shù)原型:

      VOID ExitThread(DWORD dwExitcode); 參數(shù):

      ·dwExitcode:定義調(diào)用線程的退出代碼。使用GetExitcodeThread函數(shù)來檢測一個線程的退出代碼。返回值:無。備注:

      調(diào)用ExitThread函數(shù),是結(jié)束一個線程的較好的方法。調(diào)用該函數(shù)后(或者直接地調(diào)用,或者從一個線程過程返回),當(dāng)前線程的堆棧取消分配,線程終止。若調(diào)用該函數(shù)時,該線程為進程的最后一個線程,則該線程的進程也被終止。

      線程對象的狀態(tài)變?yōu)榘l(fā)信號狀態(tài),以釋放所有正在等待該線程終止的其他線程。線程的終止?fàn)顟B(tài)從STILL-ACTIVATE變?yōu)閐wExitcode參數(shù)的值。

      線程結(jié)合時不必從操作系統(tǒng)中移去該線程對象。當(dāng)線程的最后一個句柄關(guān)閉時,該線程對象被刪除。

      3.SLEEP 函數(shù)功能:

      該函數(shù)對于指定的時間間隔掛起當(dāng)前的執(zhí)行線程。函數(shù)原型:

      VOID SLEEP(DWORD dwMilliseconds); 參數(shù):

      ·dwMilliseconds:定義掛起執(zhí)行線程的時間,以毫秒(ms)為單位。取值為0時,該線程將如余下的時間片交給處于就緒狀態(tài)的同一優(yōu)先級的其他線程。若沒有處于就緒狀態(tài)的同一優(yōu)先級的其他線程,則函數(shù)立即返回,該線程繼續(xù)執(zhí)行。若取值為INFINITE則造成無限延遲。返回值:

      該函數(shù)沒有返回值。備注:

      一個線程可以在調(diào)用該函數(shù)時將睡眠時間設(shè)為0ms,以將剩余的時間片交出。4.CreateMutex 函數(shù)功能:

      該函數(shù)創(chuàng)建有名或者無名的互斥對象。函數(shù)原型:

      HANDLE CreateMutex(LPSECURITY-ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,LPCTSTR lpName);參數(shù):

      ·lpMutexAttributes:指向SECURITY-ATTRIBUTES結(jié)構(gòu)的指針,該結(jié)構(gòu)決定子進程是否能繼承返回句柄。如果lpMutexAttributes為NULL,那么句柄不能被繼承。

      在Windows NT中該結(jié)構(gòu)的lpSwcurityDescriptor成員指定新互斥對象的安全性描述符。若lpThreadAttributes為NULL,那么互斥對象獲得默認的安全性描述符?!InitialOwner:指定互斥對象的初始所屬身份。如果該值為TRUE,并且調(diào)用者創(chuàng)建互斥對象,那么調(diào)用線程獲得互斥對象所屬身份。否則,調(diào)用線程不能獲得互斥對象所屬身份。判斷調(diào)用者是否創(chuàng)建互斥對象請參閱返回值部分。

      ·lpName:指向以NULL結(jié)尾的字符串,該字符串指定了互斥對象名。該名字的長度大于MAX-PATH且可以包含除反斜線()路徑分隔符以外的任何字符。名字是區(qū)分大小寫的。

      如果lpName與已存在的有名互斥對象相匹配,那么該函數(shù)要求用MUTEX-ALL-ACCESS權(quán)限訪問已存在的對象。在這種情況下,由于參數(shù)bInitialOwner已被創(chuàng)建進程所設(shè)置,該參數(shù)被忽略。如果參數(shù)lpMutexAttributes不為NULL,它決定句柄是否解除繼承,但是其安全描述符成員被忽略。

      如果lpName為NULL,那么創(chuàng)建的互斥對象無名。

      如果lpName與已存在的事件、信號量、可等待定時器、作業(yè)或者文件映射對象的名字相匹配,那么函數(shù)調(diào)用失敗,并且GetLastError函數(shù)返回ERROR-INVALID-HANDLE,其原因是這些對象共享相同的名字空間。

      返回值:

      如果函數(shù)調(diào)用成功,返回值為互斥對象句柄;如果函數(shù)調(diào)用之前,有名互斥對象已存在,那么函數(shù)給已存在的對象返回一個句柄,并且函數(shù)GetLastError返回ERROR-ALREADY-EXISTS,否則,調(diào)用者創(chuàng)建互斥對象。

      如果函數(shù)調(diào)用失敗,則返回值為NULL。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      備注:

      由函數(shù)CreateMutex返回的句柄有MUTEX-ALL-ACCESS權(quán)限可以去訪問新的互斥對象,并且可用在請求互斥對象句柄的任何函數(shù)中。

      調(diào)用進程中的任何線程可以可以在調(diào)用等待函數(shù)時指定互斥對象句柄。當(dāng)指定對象的狀態(tài)為信號態(tài)時,返回單對象等待函數(shù)。當(dāng)任何一個或者所有的互斥對象都為信號態(tài)時,返回多對象等待函數(shù)指令。等待函數(shù)返回后,等待的線程被釋放,繼續(xù)向下執(zhí)行。

      當(dāng)一個互斥對象不被任何線程擁有時,處于信號態(tài)。創(chuàng)建該對象的線程可以使用bInitialOwner標志來請求立即獲得對該互斥對象的所有權(quán)。否則,線程必須使用等待函數(shù)來請求所有權(quán)。當(dāng)互斥對象處于信號態(tài),等待的線程獲得對該對象的所有權(quán)時,此互斥對象的狀態(tài)被設(shè)置為非信號態(tài),等待函數(shù)返回。任意時刻,僅有一個線程能擁有該互斥對象,線程可以使用ReleaseMutex函數(shù)來釋放對這個互斥對象的所有權(quán)。

      若線程已經(jīng)擁有了一個互斥對象,那么它可以重復(fù)調(diào)用等待函數(shù)而不會發(fā)生阻塞,一般情況下,用戶不會重復(fù)等待同一個互斥對象,這種機制防止了線程因等待它已經(jīng)擁有的互斥對象而發(fā)生死鎖。然而,線程必須為每一次等待調(diào)用一次ReleaseMutex函數(shù)來釋放該互斥對象。

      兩個或多個互斥進程可以調(diào)用CreateMutex來創(chuàng)建同名的互斥對象,第一個進程實際創(chuàng)建互斥對象,以后的進程打開已存在的互斥對象的句柄。這使得多個進程可以得到同一個互斥對象的句柄,從而減輕了用戶的負擔(dān),使用戶不必判斷創(chuàng)建進程是否為第一個啟動的進程。使用這種技術(shù)時,應(yīng)該把bInitialOwner標志設(shè)為FALSE;否則很難確定開始時哪一個進程擁有該互斥對象。

      由于多進程能夠擁有相同互斥對象的句柄,通過使用這個對象,可使多進程同步。以下為共享對象機制:

      ·如果CreateMutex中的lpMutexAttributes參數(shù)允許繼承,由CreateProcess函數(shù)創(chuàng)建的子進程可以繼承父進程的互斥對象句柄。

      ·一個進程可以在調(diào)用DuplicateHandle函數(shù)時指定互斥對象句柄來創(chuàng)建一個可以被其他進程使用的雙重句柄。一個進程在調(diào)用OpenMutex或CreateMutex函數(shù)時能指定互斥對象名。

      ·使用CloseHandle函數(shù)關(guān)閉句柄,進程時系統(tǒng)自動關(guān)閉句柄。當(dāng)最后一個句柄被關(guān)閉時,互斥對象被銷毀。

      5.ReleaseMutex 函數(shù)功能:

      該函數(shù)放棄指定互斥對象的所有權(quán)。函數(shù)原型:

      BOOL ReleaseMutex(HANDLE hMutex); 參數(shù):

      ·hMutex:互斥對象句柄。為CreateMutex或OpenMutex函數(shù)的返回值。返回值:

      如果函數(shù)調(diào)用成功,那么返回值是非零值;如果函數(shù)調(diào)用失敗,那么返回值是零值。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      備注:

      如果調(diào)用線程不擁有互斥對象,ReleaseMutex函數(shù)失敗。一個線程通過調(diào)用等待函數(shù)擁有互斥對象。創(chuàng)建該互斥對象的線程也擁有互斥對象,而不需要調(diào)用等待函數(shù)。當(dāng)互斥對象的所有者線程不再需要互斥對象時,它可以調(diào)用ReleaseMutex函數(shù)。

      當(dāng)一個線程擁有一個互斥對象后,它可以用該互斥對象多次調(diào)用等待函數(shù)而不會阻塞。這防止一個線程等待一個它擁有的互斥對象時出現(xiàn)死鎖。不過,為了釋放所有權(quán),該線程必須為每一個等待操作調(diào)用一次ReleaseMutex函數(shù)。

      6.WaitForSingleObject 函數(shù)功能:

      當(dāng)下列情況之一發(fā)生時該函數(shù)返回:(1)指定對象處于信號態(tài);(2)超時。函數(shù)原型:

      DWORD waitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);參數(shù):

      ·hHandle:等待對象句柄。若想了解指定句柄的對象類型列表,參閱下面?zhèn)渥⒉糠帧?/p>

      在Windows NT中,句柄必須有SYNCHRONIZE訪問權(quán)限。若想獲得更多的信息,請查看Standard Access Rights。

      ·dwMilliseconds:指定以毫秒為單位的超時間隔。如果超時,即使對象的狀態(tài)是非信號態(tài)的并且沒有完成,函數(shù)也返回。如果dwMilliseconds是0,函數(shù)測試對象的狀態(tài)并立即返回;如果dwMilliseconds是INFINITE,函數(shù)從不超時。返回值:

      如果函數(shù)調(diào)用成功,返回值表明引起函數(shù)返回的事件??赡苤等缦拢?/p>

      ·WAIT-ABANDONED:指定對象是互斥對象,在線程被終止前,線程沒有釋放互斥對象?;コ鈱ο蟮乃鶎訇P(guān)系被授予調(diào)用線程,并且該互斥對象被置為非信號態(tài)?!AIT-OBJECT-0:指定對象的狀態(tài)被置為信號態(tài)。

      ·WAIT-TIMEOUT:超時,并且對象的狀態(tài)為非信號態(tài)。

      如果函數(shù)調(diào)用失敗,返回值是WAIT-FAILED。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      備注:

      waitForSingleObjects函數(shù)決定等待條件是否被滿足。如果等待條件并沒有被滿足,調(diào)用線程進入一個高效的等待狀態(tài),當(dāng)?shù)却凉M足條件時占用非常少的處理機時間。

      在運行前,一個等待函數(shù)修改同步對象類型的狀態(tài)。修改僅發(fā)生在引起函數(shù)返回的對象身上。例如,信號的計數(shù)減1。

      WaitForSingleObjects函數(shù)能等待的對象包括:Change notification(改變通告);Consoleinput(控制臺輸入);Event(事件);Job(作業(yè));Mutex(互斥對象);Process(進程);Semaphore(信號量);Thread(線程);Waitable timer(可等待定時器)。

      當(dāng)使用等待函數(shù)或代碼直接或間接創(chuàng)建窗口時,一定要小心。如果一個線程創(chuàng)建了任何窗口,它必須處理進程消息。消息廣播被發(fā)送到系統(tǒng)的所有窗口。一個線程用沒有超時的等待函數(shù)也許會引起系統(tǒng)死鎖。間接創(chuàng)建窗口的兩個例子是DDE和COM CoInitialize。因此,如果用戶有一個創(chuàng)建窗口的線程,用MsgWaitForMultipleObjects或MsgWaitForMultipleObjectsEx函數(shù),而不要用SignalObjectAndWait函數(shù)。

      7.WaitForMultipleObjects 函數(shù)功能:

      WaitForMultipleObjects函數(shù)當(dāng)下列條件之一滿足時返回:(1)任意一個或全部指定對象處于信號態(tài);(2)超時間隔以過。

      函數(shù)原型:

      DWORD WaitForMultipleObjects(DWORD nCount,CONST HANDLE *lpHandles, BOOL fWaitAll,DWORD dwMilliseconds);參數(shù):

      ·nCount:指定由lpHandles所指向的數(shù)組中的句柄對象數(shù)目MAXIMUM-WAIT-OBJECTS。

      ·lpHandles:指向?qū)ο缶浔鷶?shù)組的指針。該數(shù)組可以包含不同類型對象的句柄。在Windows NT中,句柄必須有SYNCHRONIZE訪問權(quán)限。若想獲得更多的信息,請查看Standard Access Rights。

      ·fWaitall:指定等待類型。如果為TRUE,當(dāng)lpHandles指向的數(shù)組里的全部對象為信號態(tài)時,函數(shù)返回。如果為FALSE,當(dāng)由lpHandles指向的數(shù)組里的任一對象為信號態(tài)時,函數(shù)返回。對于后者,返回值指出引起函數(shù)返回的對象。

      ·dwMilliseconds:指定以毫秒為單位的超時間隔。如果超時,即使bWaitAll參數(shù)指定的條件沒有滿足,函數(shù)也返回。如果dwMilliseconds是0,函數(shù)測試對象的狀態(tài)并立即返回;如果dwMilliseconds是INFINITE,函數(shù)從不超時。

      返回值:

      如果函數(shù)調(diào)用成功,返回值表明引起函數(shù)返回的事件。可能值如下:

      ·WAIT-OBJECT-0到WAIT-OBJECT-0+nCount-1:如果bWaitAll為TRUE,那么返回值表明所有指定對象的狀態(tài)為信號態(tài)。如果bWaitAll為FALSE,那么返回值減去WAIT-OBJECT-0表明引起函數(shù)返回的對象的pHandles數(shù)組索引。如果多于一個對象變?yōu)樾盘枒B(tài),則返回的是數(shù)組索引最小的信號態(tài)對象索引。

      ·WAIT-ABANDONED-0到·WAIT-ABANDONED-0+ nCount-1:如果bWaitAll為TRUE,那么返回值表明所有指定對象的狀態(tài)為信號態(tài),并且至少一個對象是已放棄的互斥對象。如果bWaitAll為FALSE,那么返回值減去WAIT-OBJECT-0表明引起函數(shù)返回的放棄互斥對象的pHandles數(shù)組索引。

      ·WAIT-TIMEOUT:超時并且由參數(shù)bWaitAll指定的條件沒有滿足。

      如果函數(shù)調(diào)用失敗,返回值是WAIT-FAILED。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      8.CreateSemapore 函數(shù)功能:

      該函數(shù)是創(chuàng)建一個有名或者無名信號對象。函數(shù)原型:

      HANDLE CreateSwmaphore(LPSECURITY-ATTRIBUTES lpAttributes,LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);參數(shù):

      ·lpAttributes:安全屬性。如果是NULL就表示要使用默認屬性?!InitialCount:Semapore的初值。必須大于或等于0,并且小于或等于MaximumCount?!MaximumCount:Semapore的最大值。這也就是在同一時間內(nèi)能夠鎖住Semapore之線程的最多個數(shù)。

      ·lpName:Semapore的名稱(一個字符串)。任何線程(或進程)都可以根據(jù)這一名稱引用到這個Semaphore。這個值可以是NULL,意思是產(chǎn)生一個沒有名字的Semaphore。

      返回值:

      如果成功就傳回一個handle,否則傳回NULL。不論哪一種情況,GetLastError都會傳回一個合理的結(jié)果。如果指定的Semaphore名稱已經(jīng)存在,則該函數(shù)還是成功的,GetLastError會傳回ERROR_ALREADY_EXISTS。

      9.ReleaseSemaphore 函數(shù)功能:

      該函數(shù)將指定信號對象的計數(shù)增加一個指定的數(shù)量。函數(shù)原型:

      BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount,LPLONG lpPreviousCount);參數(shù):

      ·hSemaphore:Semaphore的handle。

      ·lReleaseCount:Semaphore現(xiàn)值的增額。該值不可以是負值或0?!pPreviousCount:借此返回Semaphore原來的值。返回值:

      如果成功,則返回TRUE。否則返回FALSE。失敗時可調(diào)用GetLastError獲得原因。備注:

      無論ReleaseSemaphore對于Semaphore所造成的當(dāng)前值怎樣增加,都絕對不會超過CreateSemaphore時所指定的ImaximumCount。

      請記住,lpPreviousCount所傳回來的是一個瞬間值。你不可以把lReleaseCount加上* lpPreviousCount,就當(dāng)做是Semaphore的當(dāng)前值,因為其他線程可能已經(jīng)改變了Semaphore的值。

      與mutex不同的是,調(diào)用ReleaseSemaphore的那個線程,并不一定就是調(diào)用WaitXxx 的那個線程。任何線程都可以在任何時候調(diào)用ReleaseSemaphore,解除被任何線程鎖定的Semaphore。10.InitializeCriticalSection 函數(shù)功能:

      該函數(shù)初始化臨界區(qū)對象。函數(shù)原型:

      VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 參數(shù):

      ·lpCriticalSection:指向臨界區(qū)對象的指針。備注:

      單進程的所有線程可以使用互斥同步機制的臨界區(qū)對象。但是,不能保證線程獲得臨界區(qū)所有權(quán)的順序,系統(tǒng)將對所有線程公平處理。

      進程負責(zé)分配臨界區(qū)對象使用的存儲空間,這可以通過聲明CRITICAL_SECTION類型的變量來完成。在使用臨界區(qū)之前,該進程的一些線程必須使用InitializeCriticalSection或InitializeCriticalSectionAndSectiom函數(shù)來初始化該臨界區(qū)對象。

      11.EnterCriticalSection 函數(shù)功能:該函數(shù)是等待指定臨界區(qū)對象的所有權(quán)。當(dāng)調(diào)用線程被賦予所有權(quán)時,該函數(shù)返回。

      函數(shù)原型:

      VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 參數(shù):

      ·lpCriticalSection:指向臨界區(qū)對象的指針。12.LeaveCriticalSection 函數(shù)功能:該函數(shù)釋放指定臨界區(qū)對象的所有權(quán)。函數(shù)原型:

      VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 參數(shù):

      ·lpCriticalSection:指向臨界區(qū)對象的指針。4.1.5參考源代碼

      下面的程序已經(jīng)在Windows 2000/XP上實現(xiàn)。用VC6.0創(chuàng)建源文件,將輸入文件命名為thread.dat并放在與源文件相同的文件夾內(nèi),編譯運行即可(本節(jié)中的參考源代碼僅供參考)。

      #include “windows.h” #include #include #include #include #include #include

      #define READER 'R'

      // 讀者 #define WRITER 'W'

      // 寫者

      #define INTE_PER_SEC 1000

      // 每秒時鐘中斷數(shù)目。#define MAX_THREAD_NUM 64

      // 最大線程數(shù)目 #define MAX_FILE_NUM 32

      // 最大數(shù)據(jù)文件數(shù)目 #define MAX_STR_LEN 32

      // 字符串長度

      int readcount=0;

      // 讀者數(shù)目 int writecount=0;

      // 寫者數(shù)目

      CRITICAL_SECTION RP_Write;

      //臨界區(qū) CRITICAL_SECTION cs_Write;CRITICAL_SECTION cs_Read;struct ThreadInfo { int

      serial;

      // 線程序號

      char entity;

      //線程類別(判斷讀者線程還是寫者線程)double delay;double persist;};

      /////////////////////////////////////////////////////////////////////////// // 讀者優(yōu)先--讀者線程 //p:讀者線程信息

      void RP_ReaderThread(void* p){

      //互斥變量

      HANDLE h_Mutex;h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,“mutex_for_readcount”);

      DWORD wait_for_mutex;

      //等待互斥變量所有權(quán) DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 讀文件持續(xù)時間 int m_serial;

      //線程序號 //從參數(shù)中獲得信息

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

      //延遲等待

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

      // 等待互斥信號,保證對readcount的訪問、修改互斥 wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//讀者數(shù)目增加 readcount++;if(readcount==1){

      //第一個讀者,等待資源

      EnterCriticalSection(&RP_Write);} ReleaseMutex(h_Mutex);

      //釋放互斥信號

      //讀文件

      printf(“Reader thread %d begins to read file.n”,m_serial);Sleep(m_persist);

      // 退出線程

      printf(“Reader thread %d finished reading file.n”,m_serial);//等待互斥信號,保證對readcount的訪問、修改互斥 wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//讀者數(shù)目減少 readcount--;if(readcount==0){

      //如果所有讀者讀完,喚醒寫者

      LeaveCriticalSection(&RP_Write);} ReleaseMutex(h_Mutex);

      //釋放互斥信號 }

      /////////////////////////////////////////////////////////////////////////// // 讀者優(yōu)先--寫者線程 //p:寫者線程信息

      void RP_WriterThread(void* p){ DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 寫文件持續(xù)時間 int m_serial;

      //線程序號 //從參數(shù)中獲得信息

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

      //延遲等待

      printf(“Writer thread %d sents the writing require.n”,m_serial);// 等待資源

      EnterCriticalSection(&RP_Write);

      //寫文件 printf(“Writer thread %d begins to Write to the file.n”,m_serial);Sleep(m_persist);

      // 退出線程

      printf(“Writer thread %d finished Writing to the file.n”,m_serial);//釋放資源

      LeaveCriticalSection(&RP_Write);}

      /////////////////////////////////////////////////////////////////////////// // 讀者優(yōu)先處理函數(shù) //file:文件名

      void ReaderPriority(char* file){ DWORD n_thread=0;

      //線程數(shù)目 DWORD thread_ID;

      //線程ID DWORD wait_for_all;

      //等待所有線程結(jié)束 //互斥對象

      HANDLE h_Mutex;h_Mutex=CreateMutex(NULL,FALSE,“mutex_for_readcount”);

      //線程對象的數(shù)組

      HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];

      readcount=0;

      // 初始化 readcount

      InitializeCriticalSection(&RP_Write);

      //初始化臨界區(qū) ifstream inFile;inFile.open(file);

      //打開文件 printf(“Reader Priority:nn”);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')

      {

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_ReaderThread),&thread_info[i],0,&thread_ID);//創(chuàng)建讀者線程

      } else{

      //創(chuàng)建寫者線程

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),&thread_info[i],0,&thread_ID);

      } }

      //等待所有線程結(jié)束

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

      /////////////////////////////////////////////////////////////////////////// // 寫者優(yōu)先--讀者線程 //p:讀者線程信息

      void WP_ReaderThread(void* p){

      //互斥變量

      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;

      //等待互斥變量所有權(quán) DWORD wait_for_mutex2;DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 讀文件持續(xù)時間 int m_serial;

      //線程序號 //從參數(shù)中獲得信息

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

      //延遲等待

      printf(“Reader thread %d sents the reading require.n”,m_serial);wait_for_mutex1= WaitForSingleObject(h_Mutex1,-1);//進入讀者臨界區(qū)

      EnterCriticalSection(&cs_Read);// 阻塞互斥對象mutex2,保證對readcount的訪問、修改互斥 wait_for_mutex2= WaitForSingleObject(h_Mutex2,-1);//修改讀者數(shù)目 readcount++;if(readcount==1){

      //如果是第一個讀者,等待寫者寫完

      EnterCriticalSection(&cs_Write);} ReleaseMutex(h_Mutex2);

      //釋放互斥信號mutex2 // 讓其他讀者進入臨界區(qū)

      LeaveCriticalSection(&cs_Write);ReleaseMutex(h_Mutex1);//讀文件

      printf(“Reader thread %d begins to read file.n”,m_serial);Sleep(m_persist);// 退出線程

      printf(“Reader thread %d finished reading file.n”,m_serial);// 阻塞互斥對象mutex2,保證對readcount的訪問、修改互斥 wait_for_mutex2= WaitForSingleObject(h_Mutex2,-1);readcount--;if(readcount==0){

      // 最后一個讀者,喚醒寫者

      LeaveCriticalSection(&cs_Write);} ReleaseMutex(h_Mutex2);

      //釋放互斥信號 } /////////////////////////////////////////////////////////////////////////// // 寫者優(yōu)先--寫者線程 //p:寫者線程信息

      void WP_WriterThread(void* p){ DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 寫文件持續(xù)時間 int m_serial;

      //線程序號 DWORD wait_for_mutex3;//互斥對象

      HANDLE h_Mutex3;h_Mutex3= OpenMutex(MUTEX_ALL_ACCESS,FALSE,“mutex3”);

      //從參數(shù)中獲得信息

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

      //延遲等待 printf(“Writer thread %d sents the writing require.n”,m_serial);

      // 阻塞互斥對象mutex3,保證對writecount的訪問、修改互斥 wait_for_mutex3= WaitForSingleObject(h_Mutex3,-1);writecount++;

      //修改讀者數(shù)目 if(writecount==1){

      //第一個寫者,等待讀者讀完

      EnterCriticalSection(&cs_Read);} ReleaseMutex(h_Mutex3);

      //進入寫者臨界區(qū)

      EnterCriticalSection(&cs_Write);//寫文件

      printf(“Writer thread %d begins to Write to the file.n”,m_serial);Sleep(m_persist);

      // 退出線程

      printf(“Writer thread %d finishing Writing to the file.n”,m_serial);

      //離開臨界區(qū)

      LeaveCriticalSection(&cs_Write);

      // 阻塞互斥對象mutex3,保證對writecount的訪問、修改互斥 wait_for_mutex3= WaitForSingleObject(h_Mutex3,-1);writecount--;

      //修改讀者數(shù)目 if(writecount==0){

      //寫者寫完,讀者可以讀

      LeaveCriticalSection(&cs_Read);} ReleaseMutex(h_Mutex3);}

      /////////////////////////////////////////////////////////////////////////// // 寫者優(yōu)先處理函數(shù) //file:文件名

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

      //線程數(shù)目 DWORD thread_ID;

      //線程ID DWORD wait_for_all;

      //等待所有線程結(jié)束

      //互斥對象

      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”);

      //線程對象

      HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];

      readcount=0;

      // 初始化 readcount writecount=0;

      // 初始化writecount InitializeCriticalSection(&cs_Write);

      //初始化臨界區(qū) InitializeCriticalSection(&cs_Read);ifstream inFile;inFile.open(file);

      //打開文件 printf(“Writer Priority:nn”);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')

      {

      //創(chuàng)建讀者線程

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),&thread_info[i],0,&thread_ID);

      } else{

      //創(chuàng)建寫者線程

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_WriterThread),&thread_info[i],0,&thread_ID);

      } }

      //等待所有線程結(jié)束

      wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);printf(“All reader and writer have finished operating.n”);} /////////////////////////////////////////////////////////////////////////////// //主函數(shù)

      int main(int argc,char* argv[]){ char ch;

      while(true){

      //打印提示信息

      printf(“************************************************n”);

      printf(“

      1:Reader Priorityn”);

      printf(“

      2:Writer Priorityn”);

      printf(“

      3:Exit Priorityn”);

      printf(“************************************************n”);

      printf(“Enter your choice(1,2 or 3): ”);

      //如果輸入信息不正確,繼續(xù)輸入

      do{

      ch=(char)_getch();

      }while(ch!= '1' &&ch!= '2' && ch!= '3');

      system(“cls”);

      //選擇3,返回

      if(ch=='3')

      return 0;

      //選擇1,讀者優(yōu)先

      else if(ch=='1')

      ReaderPriority(“thread.dat”);

      //選擇2,寫者優(yōu)先

      else if(ch=='2')

      WriterPriority(“thread.dat”);

      //結(jié)束

      printf(“nPress Any Key To Continue: ”);

      _getch();

      system(“cls”);} return 0;}

      說明:

      在Win32 API中,互斥對象Mutex與P、V中的互斥信號量有類似的地方,但也有不同:在P、V操作中的互斥信號量可以有一個任意大小的初值,但互斥對象Mutex沒有,它可以被看成是初值為1的互斥信號量。而且一個線程在取得Mutex的所有權(quán)之后,即使不調(diào)用ReleaseMutex函數(shù),在線程結(jié)束時,線程也會自動釋放Mutex的所有權(quán)。

      臨界區(qū)對象CriticalSection則與P、V操作中初值為1的互斥信號量語意相同。它在線程結(jié)束時會將CriticalSection的所有權(quán)傳遞給它的同類型線程。這樣就可以滿足在一個線程中申請所有權(quán),在另一個線程釋放所有權(quán)的要求。在讀者優(yōu)先中的write互斥信號量以及寫者優(yōu)先中的read和write互斥信號量就應(yīng)該用CriticalSection實現(xiàn)而不應(yīng)該用Mutex。

      用WaitForSingleSignal函數(shù)可以獲得一個Mutex的所有權(quán),類似于P操作,而ReleaseMutex函數(shù)可以釋放一個Mutex的所有權(quán),類似于V操作。

      用EnterCriticalSection函數(shù)可以進入一個CriticalSection,類似于P操作,而LeaveCriticalSection函數(shù)離開一個CriticalSection,類似于V操作。

      備注:

      ReaderPriority和WritePriority函數(shù)最后都有

      wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);是因為主函數(shù)要等待所有的線程都結(jié)束之后才退出。因為不知道有多少線程,所以源文件最初有:

      #define MAX_THREAD_NUM 64 //最大線程數(shù)目

      即線程最多不能超過MAX_THREAD_NUM個。線程對象的數(shù)組大小為MAX_THREAD_NUM。如果創(chuàng)建的線程沒有那么多,空間會有浪費,但是可以達到犧牲空間來節(jié)省時間的目的。

      有的書上還有其他的處理方法。一種是在主函數(shù)的最后加上Sleep(1000),即通過主函數(shù)睡眠的方法等待其他線程結(jié)束,這當(dāng)然不是一種很好的方法,因為睡眠等待的時間沒法控制。另一種方法是增加循環(huán)變量threadCount(線程的個數(shù)),每個線程結(jié)束的就會執(zhí)行語句

      threadCount--;主函數(shù)的最后測試:

      while(threadcount>0);但是這種方式會讓主函數(shù)循環(huán)等待,浪費了CPU資源。

      相比之下,考慮到運行效率,還是實例中給出的方法比較好寫些。

      第四篇:操作系統(tǒng)課程設(shè)計報告——讀者寫者問題

      操作系統(tǒng)課程設(shè)計

      題:讀者寫者問題 姓

      名:赫前進 班

      級:1020552 學(xué)

      號102055211 指導(dǎo)教師:葉瑤 提交時間:2012/12/30

      (一)實驗?zāi)康?/p>

      1.進一步理解 “臨界資源” 的概念;

      2.把握在多個進程并發(fā)執(zhí)行過程中對臨界資源訪問時的必要約束條件; 3.理解操作系統(tǒng)原理中 “互斥” 和 “同步” 的涵義。

      (二)實驗內(nèi)容

      利用程序設(shè)計語言編程,模擬并發(fā)執(zhí)行進程的同步與互斥(要求:進程數(shù)目不少于 3 個)。

      (三)、程序分析

      讀者寫者問題的定義如下:有一個許多進程共享的數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)可以是一個文件或者主存的一塊空間;有一些只讀取這個數(shù)據(jù)區(qū)的進程(Reader)和一些只往數(shù)據(jù)區(qū)寫數(shù)據(jù)的進程(Writer),此外還需要滿足以下條件:(1)任意多個讀進程可以同時讀這個文件;(2)一次只有一個寫進程可以往文件中寫;

      (3)如果一個寫進程正在進行操作,禁止任何讀進程度文件。

      實驗要求用信號量來實現(xiàn)讀者寫者問題的調(diào)度算法。實驗提供了signal類,該類通過P()、V()兩個方法實現(xiàn)了P、V原語的功能。實驗的任務(wù)是修改Creat_Writer()添加寫者進程,Creat_Reader()創(chuàng)建讀者進程。Reader_goon()讀者進程運行函數(shù)。讀優(yōu)先:要求指一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。

      讀者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一讀者正在進行讀操作,則該讀者可直接開始讀操作。

      寫優(yōu)先:一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作后才開始讀操作。

      寫者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一寫者在等待訪問共享資源,則該讀者必須等到?jīng)]有寫者處于等待狀態(tài)后才能開始讀操作。

      在Windows 7 環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含 n 個線程。用這 n 個線程來表示 n 個讀者或?qū)懻?。每個線程按相應(yīng)測試數(shù)據(jù)文件(格式見下)的要求進行讀寫操作。用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者/寫者問題。運行結(jié)果顯示要求:要求在每個線程創(chuàng)建、發(fā)出讀寫操作申請、開始讀寫操作和結(jié)束讀寫操作時分別顯示一行提示信息,以確定所有處理都遵守相應(yīng)的讀寫操作限制。

      測試數(shù)據(jù)文件包括 n 行測試數(shù)據(jù),分別描述創(chuàng)建的 n 個線程是讀者還是寫者,以及讀寫操作的開始時間和持續(xù)時間。每行測試數(shù)據(jù)包括4個字段,各個字段間用空格分隔。

      ?

      第一個字段為一個正整數(shù),表示線程序號

      ?

      第二個字段表示相應(yīng)線程角色,R 表示讀者,W 表示寫者

      ?

      第三個字段為一個正數(shù),表示讀/寫操作的開始時間:線程創(chuàng)建后,延遲相應(yīng)時間(單位為秒)后發(fā)出對共享資源的讀/寫請求

      ?

      第四個字段為一正數(shù),表示讀/寫操作的持續(xù)時間:線程讀寫請求成功后,開始對共享資源的讀/寫操作,該操作持續(xù)相應(yīng)時間后結(jié)束,并釋放共享資源 例如: 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 讀者寫者問題是操作系統(tǒng)中經(jīng)典的互斥問題:一塊數(shù)據(jù)被多個讀者和寫者的訪問,需要考慮讀寫互斥、寫寫互斥(可以同時由多個讀者讀?。?。具體的又可以分為讀者優(yōu)先和寫者優(yōu)先兩類。讀者優(yōu)先算法:

      當(dāng)新的讀者到來的時候,若當(dāng)前正有讀者在進行讀操作,則該讀者無需等待前面的寫操作完成,直接進行讀操作。設(shè)置兩個互斥信號量:

      rwmutex 用于寫者與其他讀者/寫者互斥的訪問共享數(shù)據(jù) rmutex 用于讀者互斥的訪問讀者計數(shù)器readcount var rwmutex, rmutex : semaphore := 1,1 ; int readcount = 0;cobegin

      readeri begin // i=1,2,?.P(rmutex);

      Readcount++;

      If(readcount == 1)P(rwmutex);

      V(rmutex);

      讀數(shù)據(jù);

      P(rmutex);

      Readcount--;

      If(readcount == 0)V(rwmutex);

      V(rmutex);

      End

      Writerj begin // j = 1,2,?.P(rwmutex);

      寫更新;

      V(rwmutex);

      End Coend 寫者優(yōu)先: 條件:

      1)多個讀者可以同時進行讀

      2)寫者必須互斥(只允許一個寫者寫,也不能讀者寫者同時進行)

      3)寫者優(yōu)先于讀者(一旦有寫者,則后續(xù)讀者必須等待,喚醒時優(yōu)先考慮寫者)設(shè)置三個互斥信號量:

      rwmutex 用于寫者與其他讀者/寫者互斥的訪問共享數(shù)據(jù) rmutex 用于讀者互斥的訪問讀者計數(shù)器readcount nrmutex 用于寫者等待已進入讀者退出,所有讀者退出前互斥寫操作 var rwmutex, rmutex,nrmutex : semaphore := 1,1,1 ; int readcount = 0;cobegin

      readeri begin // i=1,2,?.P(rwmutex);

      P(rmutex);

      Readcount++;

      If(readcount == 1)P(nrmutex);//有讀者進入,互斥寫操作

      V(rmutex);

      V(rwmutex);// 及時釋放讀寫互斥信號量,允許其它讀、寫進程申請資源

      讀數(shù)據(jù);

      P(rmutex);

      Readcount--;

      If(readcount == 0)V(nrmutex);//所有讀者退出,允許寫更新

      V(rmutex);

      End

      Writerj begin // j = 1,2,?.P(rwmutex);// 互斥后續(xù)其它讀者、寫者

      P(nrmutex);//如有讀者正在讀,等待所有讀者讀完

      寫更新;

      V(nrmutex);//允許后續(xù)新的第一個讀者進入后互斥寫操作

      V(rwmutex);//允許后續(xù)新讀者及其它寫者

      End Coend //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*---------函數(shù)聲明---------*/ void Creat_Writer();

      //添加一個寫者 void Del_Writer();

      //刪除一個寫者 void Creat_Reader();

      //添加一個讀者

      void Reader_goon();

      //讀者進程運行函數(shù) void R_Wakeup();

      //喚醒等待讀者 void Del_Reader();

      //刪除一個讀者 void Show();

      //顯示運行狀態(tài)

      /*===============

      class

      signal

      ===============*/ class signal //信號量對象.{ private: int value;int queue;

      //用int型數(shù)據(jù)模擬等待隊列.public: signal();signal(int n);int P();//檢查臨界資源 int V();//釋放臨界資源 int Get_Value();int Get_Queue();};//////////////////////////////////////////////////////////////////// #include

      #include #include #include using namespace std;const int MaxThread=20;

      struct ThreadInfo

      {

      int num;

      char type;

      double start;

      double time;

      }thread_info[MaxThread];

      HANDLE hX;

      HANDLE hWsem;

      HANDLE thread[MaxThread];int readcount;double totaltime;

      void WRITEUNIT(int iProcess){

      printf(“Thread %d begins to write.n”,iProcess);

      Sleep((DWORD)(thread_info[iProcess-1].time*1000));

      printf(“End of thread %d for writing.n”,iProcess);}

      void READUNIT(int iProcess){

      printf(“Thread %d begins to read.n”,iProcess);

      Sleep((DWORD)(thread_info[iProcess-1].time*1000));

      printf(“End of thread %d for reading.n”,iProcess);}

      DWORD

      WINAPI

      reader(LPVOID

      lpVoid){

      int iProcess

      =

      *(int*)lpVoid;

      Sleep((DWORD)(thread_info[iProcess-1].start*1000));

      DWORD wait_for=WaitForSingleObject(hX,INFINITE);

      printf(“Thread %d 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);

      return iProcess;}

      DWORD

      WINAPI

      writer(LPVOID

      lpVoid){

      int iProcess

      =

      *(int*)lpVoid;

      Sleep((DWORD)(thread_info[iProcess-1].start*1000));

      printf(“Thread %d 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;

      file.open(“thread.dat”,ios::in);

      if(file==0)

      {

      printf(“File Open Error.n”);

      return 0;

      }

      while(file>>threadNum)

      {

      thread_info[threadNum-1].num=threadNum;

      file>>thread_info[threadNum-1].type;

      file>>thread_info[threadNum-1].start;

      file>>thread_info[threadNum-1].time;

      totaltime+=thread_info[threadNum-1].time;

      switch(thread_info[threadNum-1].type)

      {

      case 'W':

      printf(“Creating Thread %d writing.n”,thread_info[threadNum-1].num);

      thread[threadNum-1]

      =

      CreateThread(NULL, &thread_info[threadNum-1].num,0,0);

      break;

      case 'R':

      printf(“Creating Thread %d reading.n”,thread_info[threadNum-1].num);

      thread[threadNum-1]

      =

      CreateThread(NULL, &thread_info[threadNum-1].num,0,0);

      break;

      }

      threadcount++;

      }

      file.close();

      Sleep((DWORD)(totaltime*1000));

      return 1;} ////////////////////////////////////////////////////////////////////////////////// semaphore fmutex = 1 , rdcntmutex = 1;// fmutex--> access to file;rdcntmutex--> access to readcount int readcount = 0;void reader(){

      while(1)

      for 0,writer, for 0,reader,{

      P(rdcntmutex);

      if(readcount==0)

      P(fmutex);

      readcount = readcount + 1;

      V(rdcntmutex);

      // Do read operation

      P(rdcntmutex);

      readcount = readcount1;

      if(readcount==0)

      V(fmutex);

      V(rdcntmutex);

      } } void writer(){

      while(1)

      {

      P(wtcntmutex);

      if(writecount==0)

      P(queue);

      writecount = writecount + 1;

      V(wtcntmutex);

      P(fmutex);

      // Do write operation

      V(fmutex);

      P(wtcntmutex);

      writecount = writecount-1;

      if(writecount==0)

      V(queue);

      V(wtcntmutex);

      } }

      第五篇:怎么寫生物實驗報告

      實驗報告一般分為以下幾個部分:

      一、實驗名稱。

      二、實驗原理。將該實驗的主要原理用簡明扼要的語言進行歸納總結(jié)。

      三、實驗儀器和材料。如果所用儀器和材料較多,可寫重要的部分,常用的可以不寫。

      四、實驗步驟。該實驗如何操作的,方法和順序??梢杂梅娇驁D表示,這樣一目了然。

      五、實驗結(jié)果。將該實驗最后結(jié)果用文字或圖表的方式進行表達。推薦用表格或圖進行表示。要注意將度量單位寫清楚。

      六、實驗討論。該部分主要對上述實驗結(jié)果進行討論。有的是對實際操作中實驗現(xiàn)象或結(jié)果和實驗指導(dǎo)不一致的原因進行討論,有的是對實際操作中產(chǎn)生的實驗現(xiàn)象的原理或原因進行討論,有的是對實際操作中可以改進的方法進行討論,有的是對該實驗的進一步應(yīng)用進行討論等等。

      下載讀者寫者實驗報告word格式文檔
      下載讀者寫者實驗報告.doc
      將本文檔下載到自己電腦,方便修改和收藏,請勿使用迅雷等下載。
      點此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進行舉報,并提供相關(guān)證據(jù),工作人員會在5個工作日內(nèi)聯(lián)系你,一經(jīng)查實,本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦

        書法者必寫繁體字

        書法人必寫繁體字,這是書法文字常識,所以應(yīng)學(xué)習(xí)總結(jié),避免差錯。如茶"幾"寫成幾何之"幾","皇后"寫成前后之"後",攪"和"寫成和平之"龢",意我之"余"寫成多余之"餘",千萬"里"寫成里外之......

        “者”字型排比句40例,寫材料通俗易懂!

         1.做改革開放路上堅毅的“忠實信仰者”,做改革開放路上有擔(dān)當(dāng)?shù)摹把鐾强照摺?,做改革開放路上只爭朝夕的“腳踏實地者”。2.堅定政治忠誠,做政治上的清醒明白者;堅守政治擔(dān)當(dāng)......

        待崗者巧寫“求職書”

        待崗者巧寫“求職書”,關(guān)鍵詞是求職,當(dāng)你走進熙熙攘攘的招聘會,好容易找到家中意的單位,一個適合你的“空缺”,攤前卻堆滿了人,你費力擠進去,可工作人員忙得焦頭爛額,根本無暇聽你......

        讀者讀書筆記

        《讀者》讀書筆記 ① 《母親不是圣人》,講得是母親的一個女兒總因為母親的信心而耿耿于懷,直至有一天,她忽然明白:真正能完美唯有那些圣人。而母親,不是圣人,雖然她愛每一個孩子,......

        讀者觀后感

        我一直都很喜歡《讀者》這本書,覺得它里面每篇幅短短的故事,或讓你深受心靈的洗滌,或告訴你一個深深的道理,讓人印象深刻。最近和兒子親子閱讀,我建議大家一起看《讀者》吧,兒子......

        讀者讀后感(大全)

        讀者讀后感范文(精選5篇)當(dāng)認真看完一本名著后,相信大家一定領(lǐng)會了不少東西,是時候靜下心來好好寫寫讀后感了。是不是無從下筆、沒有頭緒?下面是小編精心整理的讀者讀后感范文(精......

        讀者讀書筆記(通用)(合集)

        讀者讀書筆記范文(通用10篇)當(dāng)品讀完一部作品后,大家一定對生活有了新的感悟和看法,寫一份讀書筆記,記錄收獲與付出吧。想必許多人都在為如何寫好讀書筆記而煩惱吧,下面是小編為大......

        《讀者讀后感》

        最近我讀了一本叫做《讀者》的雜志,感受匪淺,《讀者讀后感》。下面我就把我的體會和心得給大家說說。《讀者》這本書告訴了我許多的道理,讓我知道了更多的知識、開闊了視野、知......