互斥與同步,吃水果,吃巧克力問題
- 一、設計目的
- 二、問題描述
- 2.1問題描述
- 2.2實驗要求
- 三、詳細設計
- 3.1算法分析
- 3.2算法僞代碼
- 3.3丈夫算法流程圖
- 3.4妻子算法流程圖
- 3.5小狗算法流程圖
- 3.6小貓算法流程圖
- 四、源代碼(C++)
一、設計目的
了解、體會、運用、掌握作業系統互斥與同步。
二、問題描述
2.1問題描述
房間有一隻碗,每次隻能放入一個巧克力。丈夫專向碗中放黑巧克力,妻子專向碗中放白巧克力,小狗專等吃碗裡的黑巧克力,小貓專等吃碗裡的白巧克力。隻要碗空,則丈夫或妻子都可以向碗放一個巧克力,僅當碗中有自己需要的巧克力時,小狗或小貓可以從碗中取出巧克力。
2.2實驗要求
- 每次隻能放進一塊;
- 每次隻能拿出一塊;
- 放進和拿出不能同時發生;
- 在同一時間,隻能有一種寵物吃一塊;
- 在同一時間,隻能有一個人放進一塊;
- 丈夫放黑色的,妻子放白色的;
- 小狗隻吃黑色的,小貓隻吃白色的;
三、詳細設計
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丈夫算法流程圖
圖3-2 父親算法流程圖
3.4妻子算法流程圖
圖3-3 母親算法流程圖
3.5小狗算法流程圖
圖3-3 小狗算法流程圖
3.6小貓算法流程圖
四、源代碼(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;
}