2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、<p><b>  臨界區(qū)管理實現(xiàn)</b></p><p><b>  0 引言</b></p><p>  隨著多處理機體系結構的演變和分布式與并行系統(tǒng)的發(fā)展,并發(fā)多任務的程序設計技術已愈來愈顯得重要,多線程設計模式在這些技術的發(fā)展中起著重要作用。在現(xiàn)代操作系統(tǒng)中,利用進(線)程間的并發(fā)性實現(xiàn)程序中并發(fā)成分的并行執(zhí)行,可大大提高系統(tǒng)的

2、處理能力和效率,但也可能帶來諸如執(zhí)行結果的不確定性等不良現(xiàn)象,因此并發(fā)系統(tǒng)中處理好進(線)程間的互斥與同步就顯得至關重要。C++語言中的多線程機制是解決線程間的互斥與同步問題的重要工具,其應用(如網(wǎng)絡多媒體應用、工業(yè)自動化控制等)很廣泛,很復雜且常易出錯。因此在應用程序設計過程中,要考慮多個線程如何同步使用進程的共享資源,如何讓一個線程與另一個線程協(xié)調(diào)合作,以免產(chǎn)生線程間的訪問沖突。語言提供的多線程機制能有避免同一共享互斥資源被多個線程

3、同時訪問,維護數(shù)據(jù)的一致性、安全性。生產(chǎn)者/消費者問題可作為并發(fā)進程的同步和互斥問題的一個抽象模型,廣泛應用于通信和控制系統(tǒng)中。本文基于C++語言中的多線程機制,實現(xiàn)操作系統(tǒng)中生產(chǎn)者/消費者問題,以助人們更好地透解同步概念及其實現(xiàn)方法。</p><p><b>  1 課程設計目的</b></p><p>  通過模擬操作者生產(chǎn)者經(jīng)典問題的實現(xiàn),以及關于信號量和互斥鎖

4、對于多線程的運用,深入理解操作系統(tǒng)中多線程同步法的理論知識, 加深對教材中的重要算法的理解。同時通過編程實現(xiàn)這些算法,更好地掌握操作系統(tǒng)的原理及實現(xiàn)方法,提高綜合運用各專業(yè)課知識的能力。</p><p>  2 課程設計題目和要求</p><p>  2.1 課程設計題目</p><p>  題目: 臨界區(qū)管理實現(xiàn).</p><p>  2.

5、2課程設計目的與要求</p><p><b>  初始條件:</b></p><p>  1.操作系統(tǒng):Windows</p><p>  2.程序設計語言:C++語言</p><p>  3.有界緩沖區(qū)內(nèi)設有20個存儲單元,其初值為0。放入/取出的數(shù)據(jù)項按增序設定為1-20這20個整型數(shù)。</p><

6、;p><b>  技術要求:</b></p><p>  1、 生產(chǎn)者和消費者各有兩個以上。多個生產(chǎn)者或</p><p>  多個消費者之間須有共享對緩沖區(qū)進行操作</p><p>  的函數(shù)代碼。每個生產(chǎn)者和消費者對有界緩沖</p><p>  區(qū)進行操作后,即時顯示有界緩沖區(qū)的全部內(nèi)</p>&l

7、t;p><b>  容,當前指針位置。</b></p><p>  2、 編寫多線程同步方法解決生產(chǎn)者-消費者的程</p><p>  序,并完成對進程進行模擬同步和互斥的控制。</p><p><b>  2 設計總體思路</b></p><p>  2.1 多線程編程思想</p>

8、;<p>  編寫Windows下的多線程程序,需要使用頭文件pthread.h以及windows.h.在LINUX下進行多線程編程首先要用到CreateThread()這個函數(shù).函數(shù)CreateThread()用來創(chuàng)建一個線程,它的原型為:</p><p>  HANDLE CreateThread(</p><p>  LPSECURITY_ATTRIBUTES lpTh

9、readAttributes, </p><p>  // pointer to security attributes</p><p>  DWORD dwStackSize,</p><p>  // initial thread stack size</p><p>  LPTHREAD_START_ROUTINE lpStar

10、tAddress, </p><p>  // pointer to thread function</p><p>  LPVOID lpParameter,</p><p>  // argument for new thread</p><p>  DWORD dwCreationFlags,</p><p> 

11、 // creation flags</p><p>  LPDWORD lpThreadId);</p><p>  // pointer to receive thread ID</p><p>  第一個參數(shù)是指向SECURITY_ATTRIBUTES型態(tài)的結構的指針。在Windows 98中忽略該參數(shù)。在Windows NT中,它被設為NULL。第二個參數(shù)

12、是用于新線程的初始堆棧大小,默認值為0。在任何情況下,Windows根據(jù)需要動態(tài)延長堆棧的大小。第三個參數(shù)是指向線程函數(shù)的指標。函數(shù)名稱沒有限制,但是必須以下列形式聲明:DWORD WINAPI ThreadProc (PVOID pParam) ;第四個參數(shù)為傳遞給ThreadProc的參數(shù)。這樣主線程和從屬線程就可以共享數(shù)據(jù)。第五個參數(shù)通常為0,但當建立的線程不馬上執(zhí)行時為旗標CREATE_SUSPENDED。線程將暫停直到

13、呼叫ResumeThread來恢復線程的執(zhí)行為止。第六個參數(shù)是一個指標,指向接受執(zhí)行緒ID值的變量。</p><p><b>  2.1.1線程數(shù)據(jù)</b></p><p>  在單線程的程序里,有兩種基本的數(shù)據(jù):全局變量和局部變量。但在多線程程序里,還有第三種數(shù)據(jù)類型:線程數(shù)據(jù)。它和全局變量很象,在線程內(nèi)部,各個函數(shù)可以象使用全局變量一樣調(diào)用它,但它對線程外部的其

14、它線程是不可見的。這種數(shù)據(jù)的必要性是顯而易見的。例如我們常見的變量errno,它返回標準的出錯信息。它顯然不能是一個局部變量,幾乎每個函數(shù)都應該可以調(diào)用它;但它又不能是一個全局變量,否則在A線程里輸出的很可能是B線程的出錯信息。</p><p>  ThreadHandle[0]=CreateThread(NULL,0,Producer,NULL,0,&producer1)其六個參數(shù)分別表示為安全設置,堆

15、棧大小,入口函數(shù),函數(shù)參數(shù),啟動選項,輸出線程 ID,返回線程句柄。</p><p><b>  2.1.2 互斥鎖</b></p><p>  互斥鎖用來保證一段時間內(nèi)只有一個線程在執(zhí)行一段代碼,必要性顯而易見:假設各個線程向同一個文件順序?qū)懭霐?shù)據(jù),最后得到的結果一定是災難性的.函數(shù)mutex = CreateMutex(NULL,FALSE,NULL);用來生成一

16、個互斥鎖.NULL參數(shù)表明使用默認屬性.如果需要聲明特定屬性的互斥鎖,須調(diào)用函數(shù) CreateMutex(NULL,FALSE,NULL)</p><p>  WaitForSingleObject(mutex,INFINITE)聲明開始用互斥鎖上鎖,直至調(diào)用ReleaseMutex(mutex)為止,均被上鎖,</p><p>  即同一時間只能被一個線程調(diào)用執(zhí)行.當一個線

17、程執(zhí)行到pthread_mutex_lock處時,如果該鎖此時被另一個線程使用,那么此線程被阻塞,即程序?qū)⒌却搅硪粋€線程釋放此互斥鎖.</p><p><b>  2.1.3 信號量</b></p><p>  信號量本質(zhì)上是一個非負的整數(shù)計數(shù)器,它被用來控制對公共資源的訪問。當公共資源增加時,調(diào)用函數(shù)aitForSingleObject(empty,INFINIT

18、E)增加信號量。只有當信號量值大于0時,才能使用公共資源,使用后,函數(shù)WaitForSingleObject(full,INFINITE)減少信號量。</p><p>  函數(shù) ReleaseSemaphore(full,1,NULL)用來增加信號量的值。當有線程阻塞在這個信號量上時,調(diào)用這個函數(shù)會使其中的一個線程不在阻塞,選擇機制同樣是由線程的調(diào)度策略決定的。函數(shù)ReleaseSemaphor()用來釋放信號量

19、。</p><p><b>  2.2 設計原理</b></p><p>  生產(chǎn)者線程和消費者線程共享同一個緩沖隊列,生產(chǎn)者線程向緩沖區(qū)中寫數(shù)據(jù),消費者線程從緩沖區(qū)中取數(shù)據(jù)。但兩者必須在使用緩沖隊列資源時保持互斥,否則可能會導致在寫入時產(chǎn)生數(shù)據(jù)覆蓋,在讀出時得到錯誤數(shù)據(jù)。因而要在程序中設置一個互斥鎖或公用信號量,用于保證線程間的互斥執(zhí)行。同時生產(chǎn)者線程和消費者線程必

20、須保持同步關系,因為生產(chǎn)者線程的執(zhí)行為消費者線程提供了需要的數(shù)據(jù),是其執(zhí)行的前提。反之,消費者線程的執(zhí)行為生產(chǎn)者線程騰出了空閑的緩沖單元,為寫數(shù)據(jù)提供了條件。即消費者線程執(zhí)行的前提:緩沖隊列中至少有一個單元有數(shù)據(jù);生產(chǎn)者線程執(zhí)行的前提:緩沖隊列中至少有一個單元是空的。在設計過程中,利用信號量和wait 、signal原語操作來實現(xiàn)。如圖1所示:</p><p>  圖1 生產(chǎn)者、消費者共享有界緩沖區(qū)</p&

21、gt;<p>  2.3 原語操作實現(xiàn)</p><p>  The structure of the producer process</p><p><b>  do {</b></p><p><b>  // 生產(chǎn)產(chǎn)品</b></p><p>  wait (empty);<

22、;/p><p>  wait (mutex);</p><p>  // 往Buffer中放入產(chǎn)品</p><p>  signal (mutex);</p><p>  signal (full);</p><p>  } while (true);</p><p>  The structur

23、e of the consumer process</p><p><b>  do {</b></p><p>  wait (full);</p><p>  wait (mutex);</p><p>  // 從Buffer中取出產(chǎn)品</p><p>  signal (mutex);&l

24、t;/p><p>  signal (empty);</p><p><b>  // 消費產(chǎn)品</b></p><p>  } while (true);</p><p><b>  3 開發(fā)環(huán)境與工具</b></p><p>  系統(tǒng)平臺:Windows環(huán)境</p>

25、;<p>  實現(xiàn)語言:C++語言</p><p>  開發(fā)工具:Vs2012</p><p><b>  4 概要設計</b></p><p>  4.1 數(shù)據(jù)結構設計</p><p>  通過分析課程設計要求,具體設計出如下數(shù)據(jù)結構:</p><p>  1. int buffe

26、r[20]={0};//定義緩沖區(qū)空間大小</p><p>  2.包含數(shù)據(jù)結構pthread_t 它記錄一個線程的號,主要包括下面幾個函數(shù),完成不同的功能:</p><p>  ThreadHandle[0]=CreateThread(NULL,0,Producer,NULL,0,&producer1); //創(chuàng)建一個線程。</p><p>  Exit

27、Thread(0);</p><p>  CloseHandle(ThreadHandle[0]);</p><p>  //等待一個線程結束。</p><p>  4.2 程序模塊實現(xiàn)</p><p>  4.2.1 生產(chǎn)者(Producer)模塊 </p><p>  生產(chǎn)者線程向一緩沖區(qū)中寫入數(shù)據(jù),且寫入緩沖區(qū)的

28、數(shù)目不能超過緩沖區(qū)容量。當生產(chǎn)者產(chǎn)生出數(shù)據(jù),需要將其存入緩沖區(qū)之前,首先檢查緩沖區(qū)中是否有“空”存儲單元,若緩沖區(qū)存儲單元全部用完,則生產(chǎn)者必須阻塞等待,直到消費者取走一個存儲單元的數(shù)據(jù),喚醒它。若緩沖區(qū)內(nèi)有“空”存儲單元,生產(chǎn)者需要判斷此時是否有別的生產(chǎn)者或消費者正在使用緩沖區(qū),若是有,則阻塞等待,否則,獲得緩沖區(qū)的使用權,將數(shù)據(jù)存入緩沖區(qū),釋放緩沖區(qū)的使用權,其流程圖如圖2所示:</p><p><b&

29、gt;  圖2 生產(chǎn)者流程圖</b></p><p><b>  //生產(chǎn)者線程</b></p><p>  DWORD WINAPI Producer(LPVOID lpPara)</p><p><b>  {</b></p><p><b>  do{</b>

30、</p><p>  WaitForSingleObject(empty,INFINITE); //空緩沖區(qū)減1</p><p>  WaitForSingleObject(mutex,INFINITE); //信號量上鎖</p><p>  buffer[in]=in+1; //往Buffer中放入產(chǎn)品</p>&l

31、t;p>  in=(in+1)%BUFFER_SIZE; </p><p>  //放入指針調(diào)整,為下次送出做準備</p><p>  printAll();</p><p>  ReleaseMutex(mutex); //信號量解鎖</p><p>  ReleaseSemaphore(full,1,NULL);

32、 </p><p>  //滿緩沖區(qū)加1,即當公共資源增加時,調(diào)用函數(shù)ReleaseSemaphore()增加信號量</p><p>  }while(1);</p><p><b>  }</b></p><p>  4.2.2 消費者(Consumer)模塊 </p><p>  消費者線程

33、從緩沖區(qū)中讀取數(shù)據(jù),且消費者讀取的數(shù)目不能超過生產(chǎn)者寫入的數(shù)目。消費者取數(shù)據(jù)之前,首先檢查緩沖區(qū)中是否存在裝有數(shù)據(jù)的存儲單元,若緩沖區(qū)為“空”,則阻塞等待,否則,判斷緩沖區(qū)是否正在被使用,若正被使用,若正被使用,則阻塞等待,否則,獲得緩沖區(qū)的使用權,進入緩沖區(qū)取數(shù)據(jù),釋放緩沖區(qū)的使用權。其執(zhí)行流程如圖3所示:</p><p><b>  圖3 消費者流程圖</b></p>&l

34、t;p><b>  //消費者線程</b></p><p>  DWORD WINAPI Consumer(LPVOID lpPara)</p><p><b>  {</b></p><p><b>  do{</b></p><p>  WaitForSingleOb

35、ject(full,INFINITE); //滿緩沖區(qū)減1</p><p>  WaitForSingleObject(mutex,INFINITE); //信號量上鎖</p><p>  buffer[out]=0; //從Buffer中取出產(chǎn)品</p><p>  out=(out+1)%BUFFER_SIZE; //取

36、指針調(diào)整,為下次取做準備</p><p>  printAll();</p><p>  ReleaseMutex(mutex); //信號量解鎖</p><p>  ReleaseSemaphore(empty,1,NULL); //空緩沖區(qū)加1</p><p>  }while(1);</p><p&g

37、t;<b>  }</b></p><p><b>  5 詳細設計</b></p><p><b>  5.1 源程序代碼</b></p><p>  #include<iostream></p><p>  #include <stdio.h><

38、;/p><p>  #include <pthread.h></p><p>  #include <semaphore.h></p><p>  #include <windows.h></p><p>  using namespace std;</p><p>  DWORD WI

39、NAPI Producer(LPVOID);</p><p>  DWORD WINAPI Consumer(LPVOID);</p><p>  #define WINAPI_stdcall </p><p>  #define THREAD_NUM 20</p><p>  #define BUFFER_SIZE 20 //20

40、個緩沖區(qū)</p><p>  int buffer[20]={0};</p><p>  HANDLE empty;</p><p>  HANDLE full;</p><p>  HANDLE mutex; //for mutual exclusion進程信號量</p><p>  int in=0

41、; //point to the next free positon</p><p>  int out=0; //point to the first full positon</p><p>  //把所有的緩沖區(qū)輸出到屏幕上</p><p>  void printAll(){</p><p>&l

42、t;b>  int i;</b></p><p>  for(i=0;i<20;i++)</p><p>  cout<<i<<" ";</p><p>  cout<<endl;</p><p>  cout<<"current produ

43、cer pointer:"<<in<<endl;</p><p>  cout<<"current consumer pointer:"<<out<<endl;</p><p><b>  }</b></p><p><b>  //生產(chǎn)者線程&

44、lt;/b></p><p>  DWORD WINAPI Producer(LPVOID lpPara)</p><p><b>  {</b></p><p><b>  do{</b></p><p>  WaitForSingleObject(empty,INFINITE);

45、 //空緩沖區(qū)減1</p><p>  WaitForSingleObject(mutex,INFINITE); //信號量上鎖</p><p>  buffer[in]=in+1; //往Buffer中放入產(chǎn)品</p><p>  in=(in+1)%BUFFER_SIZE; </p><p>  //放

46、入指針調(diào)整,為下次送出做準備</p><p>  printAll();</p><p>  ReleaseMutex(mutex); //信號量解鎖</p><p>  ReleaseSemaphore(full,1,NULL); </p><p>  //滿緩沖區(qū)加1,即當公共資源增加時,調(diào)用函數(shù)ReleaseSemaphore

47、()增加信號量</p><p>  }while(1);</p><p><b>  }</b></p><p><b>  //消費者線程</b></p><p>  DWORD WINAPI Consumer(LPVOID lpPara)</p><p><b>

48、;  {</b></p><p><b>  do{</b></p><p>  WaitForSingleObject(full,INFINITE); //滿緩沖區(qū)減1</p><p>  WaitForSingleObject(mutex,INFINITE); //信號量上鎖</p><p

49、>  buffer[out]=0; //從Buffer中取出產(chǎn)品</p><p>  out=(out+1)%BUFFER_SIZE; //取指針調(diào)整,為下次取做準備</p><p>  printAll();</p><p>  ReleaseMutex(mutex); //信號量解鎖</p><p>

50、  ReleaseSemaphore(empty,1,NULL); //空緩沖區(qū)加1</p><p>  }while(1);</p><p><b>  }</b></p><p><b>  //主線程</b></p><p>  int main()</p><p&g

51、t;  { //創(chuàng)建進程</p><p>  DWORD producer[THREAD_NUM],consumer[THREAD_NUM];</p><p>  mutex = CreateMutex(NULL,FALSE,NULL); // 用默認屬性初始化一個互斥變量mutex</p><p>  HANDLE ThreadHandle[

52、THREAD_NUM];</p><p><b>  // 初始化信號量</b></p><p>  full=CreateSemaphore(NULL,0,10,NULL);</p><p>  empty=CreateSemaphore(NULL,10,10,NULL);</p><p>  //CreateThre

53、ade函數(shù)用來創(chuàng)建生產(chǎn)者和消費者進程,其六個參數(shù)分別表示為安全設置,堆棧大小,入口函數(shù),函數(shù)參數(shù),啟動選項,輸出線程 ID,返回線程句柄</p><p>  for(int i=0;i<THREAD_NUM;i++)</p><p><b>  {</b></p><p>  ThreadHandle[i] = CreateThread(

54、NULL,0,Producer,NULL,0,&producer[i]);</p><p>  ThreadHandle[i] = CreateThread(NULL,0,Consumer,NULL,0,&consumer[i]);</p><p>  ThreadHandle[i+1] = CreateThread(NULL,0,Producer,NULL,0,&

55、producer[i+1]);</p><p>  ThreadHandle[i+1] = CreateThread(NULL,0,Consumer,NULL,0,&consumer[i+1]);</p><p><b>  }</b></p><p><b>  }</b></p><p>

56、;  6 程序運行結果及分析</p><p><b>  6.1 運行結果</b></p><p>  進入Windows開發(fā)環(huán)境后,通過Vs2012編輯器在其中編寫。進入Vs2012的命令,對程序執(zhí)行編譯運行命令后,即可在屏幕上顯示出程序運行的結果,其運行結果如下圖5所示:</p><p><b>  7 總結</b>&

57、lt;/p><p>  其實在做這道題目時花費了好長時間,第一點是書上大多介紹的是關于UNIX系統(tǒng)下的消費者生產(chǎn)者線程問題,因此一開始調(diào)試不出來,后來查閱了有一些資料知道要在windows平臺下運行必須要導入<pthread.h>以及<windows.h>兩個庫。</p><p>  通過這次課程設計,不但加深了對操作系統(tǒng)這們課程的認識,而且還了解了操作系統(tǒng)中使用信號量

58、解決生產(chǎn)者—消費者問題算法的實現(xiàn)。比如:用信號量解決生產(chǎn)者—消費者問題時,可以通過一個有界緩沖區(qū)(用數(shù)組來實現(xiàn),類似循環(huán)隊列)把生產(chǎn)者和消費者聯(lián)系起來。假定生產(chǎn)者和消費者的優(yōu)先級是相同的,只要緩沖區(qū)未滿,生產(chǎn)者就可以生產(chǎn)產(chǎn)品并將產(chǎn)品送入緩沖區(qū)。類似地,只要緩沖區(qū)未空,消費者就可以從緩沖區(qū)中去走產(chǎn)品并消費它。為了解決生產(chǎn)者/消費者問題,應該設置兩個資源信號量,其中一個表示空緩沖區(qū)的數(shù)目,用full表示,其初始值為有界緩沖區(qū)的大??;另一個表

59、示緩沖區(qū)中產(chǎn)品的數(shù)目,用empty表示,其初始值為0。另外,由于有界緩沖區(qū)是一個臨界資源,必須互斥使用,所以還需要再設置一個互斥信號量mutex,起初值為1。在生產(chǎn)者/消費者問題中,信號量實現(xiàn)兩種功能。首先,它是生產(chǎn)產(chǎn)品和消費產(chǎn)品的計數(shù)器,計數(shù)器的初始值是可利用的資源數(shù)目(有界緩沖區(qū)的長度)。其次,它是確保產(chǎn)品的生產(chǎn)者和消費者之間動作同步的同步器。</p><p>  生產(chǎn)者要生產(chǎn)一個產(chǎn)品時,首先對資源信號量fu

60、ll和互斥信號量mute進行操作,申請資源。如果可以通過的話,就生產(chǎn)一個產(chǎn)品,并把產(chǎn)品送入緩沖區(qū)。然后對互斥信號量mutex和資源信號量empty進行操作,釋放資源。消費者要消費一個產(chǎn)品時,首先對資源信號量empty和互斥信號量mutex進行操作,申請資源。如果可以通過的話,就從緩沖區(qū)取出一個產(chǎn)品并消費掉。然后對互斥信號量mutex和資源信號量full進行操作,釋放資源。</p><p>  另外,使我們體會最深

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論