天天看點

【作業系統】互斥與同步,吃水果,吃巧克力問題(C++源碼)

互斥與同步,吃水果,吃巧克力問題

  • ​​一、設計目的​​
  • ​​二、問題描述​​
  • ​​2.1問題描述​​
  • ​​2.2實驗要求​​
  • ​​三、詳細設計​​
  • ​​3.1算法分析​​
  • ​​3.2算法僞代碼​​
  • ​​3.3丈夫算法流程圖​​
  • ​​3.4妻子算法流程圖​​
  • ​​3.5小狗算法流程圖​​
  • ​​3.6小貓算法流程圖​​
  • ​​四、源代碼(C++)​​

一、設計目的

了解、體會、運用、掌握作業系統互斥與同步。

二、問題描述

2.1問題描述

房間有一隻碗,每次隻能放入一個巧克力。丈夫專向碗中放黑巧克力,妻子專向碗中放白巧克力,小狗專等吃碗裡的黑巧克力,小貓專等吃碗裡的白巧克力。隻要碗空,則丈夫或妻子都可以向碗放一個巧克力,僅當碗中有自己需要的巧克力時,小狗或小貓可以從碗中取出巧克力。

2.2實驗要求

  1. 每次隻能放進一塊;
  2. 每次隻能拿出一塊;
  3. 放進和拿出不能同時發生;
  4. 在同一時間,隻能有一種寵物吃一塊;
  5. 在同一時間,隻能有一個人放進一塊;
  6. 丈夫放黑色的,妻子放白色的;
  7. 小狗隻吃黑色的,小貓隻吃白色的;

三、詳細設計

3.1算法分析

丈夫和小狗是互相制約的,丈夫程序執行完,即往盤中放入黑巧克力後,小狗程序才能執行即吃黑巧克力,是同步關系;妻子和小貓是互相制約的,妻子程序執行完,即往盤中放入白巧克力,小貓程序才能執行即吃白巧克力,也是同步關系而丈夫和妻子這兩個程序不能同時進行,是互斥關系。

3.2算法僞代碼

/**********************僞代碼**********************/  
void father()  
{  
    while(true)  
    {  
        wait(empty);//等待盤空,申請臨界資源  
        produce black_chocolate;  
        signal(black_chocolate);//black_chocolate++,告知小狗有黑巧克力了  
    }  
}  
  
void mother()  
{     
    while(true)  
    {  
        wait(empty);//等待盤空,申請臨界資源  
        produce white_chocolate;  
        signal(white_chocolate);//white_chocolate++,告知小貓有白巧克力了  
    }  
}  
  
void dog()  
{     
    while(true)  
    {  
        wait(black_chocolate);//等待黑巧克力  
        consume black_chocolate  
        signal(empty);//empty++,告知爸爸盤子空了  
    }  
}  
void cat()  
{     
    while(true)  
    {  
        wait(white_chocolate);//等待白巧克力  
        consume white_chocolate  
        signal(empty);//empty++,告知媽媽盤子空了  
    }  
}      

3.3丈夫算法流程圖

【作業系統】互斥與同步,吃水果,吃巧克力問題(C++源碼)

圖3-2 父親算法流程圖

3.4妻子算法流程圖

【作業系統】互斥與同步,吃水果,吃巧克力問題(C++源碼)

圖3-3 母親算法流程圖

3.5小狗算法流程圖

【作業系統】互斥與同步,吃水果,吃巧克力問題(C++源碼)

圖3-3 小狗算法流程圖

3.6小貓算法流程圖

【作業系統】互斥與同步,吃水果,吃巧克力問題(C++源碼)

四、源代碼(C++)

#include <windows.h>
#include <iostream>
  
using namespace std;  
  
  
  
//聲明句柄    
HANDLE EmptyPlate;          //聲明空盤子  
HANDLE husbandThread;       //聲明丈夫線程  
HANDLE wifeThread;          //聲明妻子線程  
HANDLE bCoco;               //聲明黑巧克力  
HANDLE wCoco;               //聲明白巧克力  
HANDLE dogThread;           //聲明小狗線程  
HANDLE catThread;           //聲明小貓線程  
  
//線程函數聲明  
DWORD WINAPI husband(LPVOID IpParameter);       //丈夫線程函數聲明  
DWORD WINAPI wife(LPVOID IpParameter);          //妻子線程函數聲明  
DWORD WINAPI dog(LPVOID IpParameter);           //小狗線程函數聲明  
DWORD WINAPI cat(LPVOID IpParameter);           //小貓線程函數聲明  
  
//初始化黑、白巧克力  
int wConoNum = 0;           //黑巧克力定為0  
int bConoNum = 0;           //白巧克力定為0  
int num = 0;  
  
class PvTest   
{  
    public:  
        PvTest();  
        ~PvTest();  
};  
  
PvTest::PvTest()  
{  
  
}  
  
//析構回收線程以及信号量  
PvTest::~PvTest()   
{  
  
}  
  
int main()  
{  
    cout << " 請輸入線程的次數(>=0): " << endl;  
    cin >> num;  
    while (num < 0)  
    {  
        cout << " 輸入線程的次數不符合要求,請重新輸入! " << endl;  
        cout << " 請輸入線程的次數(>=0): " << endl;  
        cin >> num;  
    }  
          
    //建立信号量    
    EmptyPlate = CreateSemaphore(NULL, 1, 1, NULL);  
    bCoco = CreateSemaphore(NULL, 0, 1, NULL);                          //黑巧克力    
    wCoco = CreateSemaphore(NULL, 0, 1, NULL);                          //白巧克力    
  
    //建立線程    
    // * 參數 1 核心安全屬性 null 為預設  
    // * 參數 2 線程可用的空間大小  
    // * 參數 3 表示線程函數的位址  
    // * 參數 4 傳給線程的參數  
    // * 參數 5 控制線程建立,為 0 表示建立後立即啟動,CREATE_SUSPENDED 表示建立後先暫停  
    // * 參數 6 表示 lpTHreadId 傳回的線程 ID , 傳入 NULL 表示不需要 傳回 ID 号  
    husbandThread = CreateThread(NULL, 0, husband, NULL, 0, NULL);      //建立丈夫線程  
    wifeThread = CreateThread(NULL, 0, wife, NULL, 0, NULL);            //建立妻子線程  
    dogThread = CreateThread(NULL, 0, dog, NULL, 0, NULL);              //建立小狗線程  
    catThread = CreateThread(NULL, 0, cat, NULL, 0, NULL);              //建立小貓線程  
  
    //等線程的結束  
    WaitForSingleObject(husbandThread, INFINITE);                       //等待丈夫線程結束  
    WaitForSingleObject(wifeThread, INFINITE);                          //等待妻子線程結束  
    WaitForSingleObject(dogThread, INFINITE);                           //等待小狗線程結束  
    WaitForSingleObject(catThread, INFINITE);                           //等待小貓線程結束  
  
    //關閉線程句柄    
    CloseHandle(husbandThread);                                         //關閉丈夫線程  
    CloseHandle(wifeThread);                                            //關閉妻子線程  
    CloseHandle(dogThread);                                             //關閉小狗線程  
    CloseHandle(catThread);                                             //關閉小貓線程  
  
    //關閉信号量句柄    
    CloseHandle(EmptyPlate);                                            //關閉空盤子句柄  
    CloseHandle(wCoco);                                                 //關閉黑巧克力句柄  
    CloseHandle(bCoco);                                                 //關閉白巧克力句柄  
  
    return 0;  
}  
  
  
//丈夫線程  
DWORD WINAPI husband(LPVOID IpParameter)  
{  
    for (int i = 0; i < num; ++i)   
    {  
        WaitForSingleObject(EmptyPlate, INFINITE);              //P操作    
        // 開始臨界區  
        bConoNum++;  
        cout << "\n丈夫往盤中放一個黑巧克力\n";  
        cout << "盤子中情況:" << ((bConoNum == 1) ? "○" : "●") << endl;  
        // 結束臨界區    
        ReleaseSemaphore(bCoco, 1, NULL);                       //V操作    
        Sleep(1000);  
    }  
    return 0;  
}  
  
//妻子線程  
DWORD WINAPI wife(LPVOID IpParmeter)  
{  
    for (int i = 0; i < num; ++i)   
    {  
        WaitForSingleObject(EmptyPlate, INFINITE);              //P操作    
        // 開始臨界區    
        wConoNum++;  
        cout << "\n妻子往盤中放一個白巧克\n";  
        cout << "盤子中情況:" << (( bConoNum == 1) ? "○" : "●") << endl;  
        // 結束臨界區    
        ReleaseSemaphore(wCoco, 1, NULL);                       //V操作    
        Sleep(500);  
    }  
    return 0;  
}  
  
//小狗線程  
DWORD WINAPI dog(LPVOID IpParameter)  
{  
    for (int i = 0; i < num; ++i)  
    {  
        WaitForSingleObject(bCoco, INFINITE); //p操作    
        bConoNum--;  
        cout << "小狗吃黑巧克!" << endl;  
        ReleaseSemaphore(EmptyPlate, 1, NULL); //v操作    
    }  
    return 0;  
}  
  
//小貓線程  
DWORD WINAPI cat(LPVOID IpParameter)  
{  
    for (int i = 0; i < num; ++i)  
    {  
        WaitForSingleObject(wCoco, INFINITE); //p操作    
        wConoNum--;  
        cout << "小貓吃白巧克力!" << endl;  
        ReleaseSemaphore(EmptyPlate, 1, NULL); //v操作    
    }  
    return 0;  
}      

繼續閱讀