狠狠干影院/欧美午夜电影在线观看/高黄文/国产精品一区二区在线观看完整版

進(jìn)程(線程)同步和互斥實(shí)驗(yàn)報告

| 瀏覽次數(shù):

  操 作 系 統(tǒng) 實(shí) 驗(yàn) 報 告 課程名稱

 操作系統(tǒng)

 實(shí)驗(yàn)名稱

 進(jìn)程(線程)的同步與互斥

 成績

  學(xué)生姓名

  作業(yè)君

  專業(yè)

  軟件工程

  班級、學(xué)號

  同組者姓名

  無

  實(shí)驗(yàn)日期

 2020

  一、實(shí)驗(yàn)題目: : 進(jìn)程(線程)的同步與互斥 二、實(shí)驗(yàn)?zāi)康?:

 自行編制模擬程序,通過形象化的狀態(tài)顯示,加深理解進(jìn)程的概念、進(jìn)程之間的狀態(tài)轉(zhuǎn)換及其所帶來的 PCB 內(nèi)容 、組織的變化,理解進(jìn)程與其 PCB 間的一一對應(yīng)關(guān)系。

 1.掌握基本的同步與互斥算法,理解生產(chǎn)者消費(fèi)者模型。

 2.學(xué)習(xí)使用 Windows 中基本的同步對象,掌握相關(guān) API 的使用方法。

 3.了解 Windows 中多線程的并發(fā)執(zhí)行機(jī)制,實(shí)現(xiàn)進(jìn)程的同步與互斥 三、實(shí)驗(yàn)內(nèi)容與要求 :

 1.實(shí)驗(yàn)內(nèi)容 以生產(chǎn)者/消費(fèi)者模型為依據(jù),在 Windows 環(huán)境下創(chuàng)建一個控制臺進(jìn)程,在該進(jìn)程中創(chuàng)建 n 個線程模擬生產(chǎn)者和消費(fèi)者,實(shí)現(xiàn)進(jìn)程(線程)的同步與互斥。

 2.實(shí)驗(yàn)要求 學(xué)習(xí)并理解生產(chǎn)者/消費(fèi)者模型及其同步/互斥規(guī)則; 學(xué)習(xí)了解 Windows 同步對象及其特性; 熟悉實(shí)驗(yàn)環(huán)境,掌握相關(guān) API 的使用方法; 設(shè)計程序,實(shí)現(xiàn)生產(chǎn)者/消費(fèi)者進(jìn)程(線程)的同步與互斥;

 四、算法描述(含數(shù)據(jù)結(jié)構(gòu)定義)或流程圖

 #include <Windows.h> #include <iostream> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std;

  #define MAX_THREAD_NUM 64

  //最大線程數(shù) #define INTE_PER_SEC 1000

  //延遲時間的毫秒值 const int SIZE_OF_BUFFER = 10;

 //緩沖區(qū)長度 int ProductID = 0;

  //產(chǎn)品號 int ConsumeID = 0;

 //將被消耗的產(chǎn)品號 int in = 0;

 //產(chǎn)品進(jìn)緩沖區(qū)時的緩沖區(qū)下標(biāo) int out = 0;

  //產(chǎn)品出緩沖區(qū)時的緩沖區(qū)下標(biāo) bool running = true;

 //判斷程序能否繼續(xù)執(zhí)行的邏輯值 int g_buffer[SIZE_OF_BUFFER];

  //緩沖區(qū)是個循環(huán)隊(duì)列 HANDLE g_hMutex;

 //公有信號量,用于線程間的互斥 HANDLE g_hFullSemaphore;

  //生產(chǎn)者的私有信號量,當(dāng)緩沖區(qū)滿時迫使生產(chǎn)者等待 HANDLE g_hEmptySemaphore;

  //消費(fèi)者的私有信號量,當(dāng)緩沖區(qū)空時迫使消費(fèi)者等待

 //定義一個結(jié)構(gòu)體用于存儲線程的信息 struct ThreadInfo {

 int serial;

  //線程號

 char entity;

 //線程類別(生產(chǎn)者或消費(fèi)者)

 double delay;

  //等待時間

 double persist; //操作時間 };

 //生產(chǎn)者 void Producer(void* p) {

 //定義變量用于存儲當(dāng)前線程的信息

 DWORD m_delay;

 DWORD m_persist;

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

  while (running)

 {

  //P 操作

  cout << "生產(chǎn)者線程 " << m_serial << " 請求生產(chǎn)." << endl;

  WaitForSingleObject(g_hEmptySemaphore, INFINITE);

  cout << "生產(chǎn)者線程 " << m_serial << " 請求獨(dú)占緩沖區(qū)." << endl;

  WaitForSingleObject(g_hMutex, INFINITE);

 Sleep(m_delay);

 //延遲等待

  //生產(chǎn)一個產(chǎn)品

  cout << "生產(chǎn)者線程 " << m_serial << " 生產(chǎn) " << ++ProductID << " 號產(chǎn)品成功." << endl;

  cout << "生產(chǎn)者線程 " << m_serial << " 請求將產(chǎn)品 " << ProductID << " 投入緩沖區(qū)." << endl;

  //把新生產(chǎn)的產(chǎn)品放入緩沖區(qū)

  g_buffer[in] = ProductID;

  in = (in +1)%SIZE_OF_BUFFER;

  Sleep(m_persist);

  //操作等待

  cout << "生產(chǎn)者線程 " << m_serial << " 將產(chǎn)品 " << ProductID << " 投入緩沖區(qū)中成功." << endl;

 //輸出緩沖區(qū)當(dāng)前的狀態(tài)

  cout << "****************************" << endl

 << "\n 當(dāng)前緩沖區(qū)情況如圖(■代表已有產(chǎn)品,□代表沒有產(chǎn)品):

  " << endl;

  for (int i = 0;i < SIZE_OF_BUFFER;++i)

  {

 if (g_buffer[i] != 0)

  cout << "■";

 else

 cout << "□";

  }

  cout << "\n\n****************************\n" << endl;

 //V 操作

  ReleaseMutex(g_hMutex);

  ReleaseSemaphore(g_hFullSemaphore, 1, NULL);

 } }

 //消費(fèi)者 void Consumer(void* p) {

 DWORD m_delay;

 DWORD m_persist;

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

 while (running)

 {

  //P 操作

  cout << "消費(fèi)者線程 " << m_serial << " 請求消費(fèi)." << endl;

  WaitForSingleObject(g_hFullSemaphore, INFINITE);

  cout << "消費(fèi)者線程 " << m_serial << " 請求獨(dú)占緩沖區(qū)." << endl;

  WaitForSingleObject(g_hMutex,INFINITE);

 Sleep(m_delay); //延遲等待

  //從緩沖區(qū)中取出一個產(chǎn)品

  cout << "消費(fèi)者線程 " << m_serial << " 請求取出一個產(chǎn)品." << endl;

  ConsumeID = g_buffer[out];

  g_buffer[out] = 0;

  out = (out + 1) % SIZE_OF_BUFFER;

  cout << "消費(fèi)者線程 " << m_serial << " 取出產(chǎn)品 " << ConsumeID << " 成功." << endl;

 //消耗一個產(chǎn)品

  cout << "消費(fèi)者線程 " << m_serial << " 開始消費(fèi)消費(fèi)產(chǎn)品 " << ConsumeID << "." << endl;

  Sleep(m_persist);

  cout << "消費(fèi)者線程 " << m_serial << " 消費(fèi)產(chǎn)品 " << ConsumeID << " 成功." << endl;

 //輸出緩沖區(qū)當(dāng)前的狀態(tài)

  cout << "****************************" << endl

 << "\n 當(dāng)前緩沖區(qū)情況如圖:

  " << endl;

  for (int i = 0;i < SIZE_OF_BUFFER;++i)

  {

 if (g_buffer[i] != 0)

  cout << "■";

 else

 cout << "□";

  }

  cout << "\n\n****************************\n" << endl;

 //V 操作

  ReleaseMutex(g_hMutex);

  ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);

 } }

 void prod_cons() {

 //創(chuàng)建互斥信號量

 g_hMutex = CreateMutex(NULL, FALSE, NULL);

 //創(chuàng)建同步信號量

 g_hEmptySemaphore = CreateSemaphore(NULL, SIZE_OF_BUFFER, SIZE_OF_BUFFER, NULL);

 g_hFullSemaphore = CreateSemaphore(NULL, 0, SIZE_OF_BUFFER, NULL);

 srand((unsigned)time(NULL));

 //以時間函數(shù)為種子

 const unsigned short THREADS_COUNT = rand() % 5 + 5; //總的線程數(shù)(隨機(jī)生成)

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

 HANDLE hThreads[MAX_THREAD_NUM];

 ThreadInfo thread_info[MAX_THREAD_NUM];

  DWORD thread_ID; //線程 ID

 int num = 0;

  //臨時變量,用于循環(huán)語句

 cout << "系統(tǒng)開始模擬,并自動生成模擬數(shù)據(jù)..." << endl;

 system("pause"); //暫停確認(rèn)開始執(zhí)行

 cout << "線程總數(shù):" << THREADS_COUNT << endl;

  //循環(huán)隨機(jī)生成各個線程的信息

 while (num != THREADS_COUNT)

 {

  thread_info[num].serial = num + 1;

  if (rand() % 2 == 1)

 thread_info[num].entity = "P";

  else

 thread_info[num].entity = "C";

  thread_info[num].delay = rand() % 5 + 1;

  thread_info[num].persist = rand() % 6 + 2;

  num++;

 }

  cout << "\n 系統(tǒng)生成數(shù)據(jù)結(jié)束,模擬數(shù)據(jù)如下:" << endl

  << "線程號

 線程類別

 延遲時間

 操作時間" << endl;

 for (int x = 0;x < THREADS_COUNT;x++)

  cout << "

 " << thread_info[x].serial << "\t"

  << "

  " << thread_info[x].entity << "\t"

  << "

 " << thread_info[x].delay << "\t\t"

  << "

  " << thread_info[x].persist << endl;

 cout << "\n\n==================生產(chǎn)者-消費(fèi)者 開始==================\n" << endl;

  //創(chuàng)建線程

 for (int i = 0;i < THREADS_COUNT;i++)

 {

  //創(chuàng)建生產(chǎn)者線程

  if (thread_info[i].entity == "P")

 hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(Producer), &thread_info[i], 0, &thread_ID);

  //創(chuàng)建消費(fèi)者線程

  else

 hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(Consumer), &thread_info[i], 0, &thread_ID);

 }

  while (running)

 {

  if (getchar())

  {

 //按回車后終止程序運(yùn)行

 running = false;

  }

 }

 cout << "系統(tǒng)模擬結(jié)束..." << endl; } int main() {

 cout << "\n==================生產(chǎn)者-消費(fèi)者 模擬==================\n" << endl;

 prod_cons(); }

 五、實(shí)驗(yàn)過程

 1、記錄生產(chǎn)者和消費(fèi)者的同步執(zhí)行過程。

  2、分析 Producer 函數(shù)和 Consumer 函數(shù)的功能,并畫出對應(yīng)的程序流程圖。

  Producer 函數(shù):調(diào)用函數(shù),獲取資源情況,然后判斷條件是否滿足,判斷是否執(zhí)行,接著發(fā)出生產(chǎn)請求,請求通過后獨(dú)占緩沖區(qū)資源,接著生產(chǎn)-一個產(chǎn)品投入緩沖區(qū),成功后釋放所占緩沖區(qū)資源,到此此函數(shù)執(zhí)行完成。

 consumer 函數(shù):

 通過用變量提取保存提取當(dāng)前資源信息, 然后判斷是否執(zhí)行, 接著發(fā)出消費(fèi)請求, 請求通過后獨(dú)占緩沖區(qū)資源, 接著消費(fèi)一個產(chǎn)品取出緩沖區(qū), 成功后釋放所占緩沖區(qū)資源, 到此此函數(shù)執(zhí)行完成。

 3、試將同步和互斥的 P 操作顛倒次序執(zhí)行,觀察并分析程序的運(yùn)行情況。

 答:

 如將同步和互斥的 P 操作顛倒次序執(zhí)行,程序會產(chǎn)生死鎖。因?yàn)檫@個操作會先獨(dú)占緩沖區(qū)的資源,然后才發(fā)送請求。如果生產(chǎn)或者消費(fèi)請求無法通過而一直等待下去的話,則無法釋放資源,進(jìn)而產(chǎn)生程序的死鎖,使得程序無法運(yùn)行!

 六、實(shí)驗(yàn)總結(jié)

 通過本次實(shí)驗(yàn),讓我對線程的同步與互斥技術(shù)有了比較深刻的了解,生產(chǎn)者消費(fèi)者問題是研究多線線程程序繞不開的問題,它的描述是有一塊生產(chǎn)者和消費(fèi)者共享的有界緩沖區(qū),生產(chǎn)者往緩沖區(qū)放入產(chǎn)品,消費(fèi)者從緩沖區(qū)取走產(chǎn)品,這個過程可以無休止的進(jìn)行,不能因緩沖區(qū)滿生產(chǎn)者放不進(jìn)產(chǎn)品而終止,也不能因緩沖區(qū)空消費(fèi)者無產(chǎn)品可取而終止。

推薦訪問: 線程 進(jìn)程 同步

【進(jìn)程(線程)同步和互斥實(shí)驗(yàn)報告】相關(guān)推薦

工作總結(jié)最新推薦

NEW