问题描述:桌上有一空盘,最多允许存放一个水果。爸爸可向盘中放一个苹果或放一个桔子,儿子专等吃盘中的桔子,女儿专等吃苹果。 编写Windows下父亲儿子女儿放取水果进程同步的演示程序。
问题分析及思路:
- 本题是生产者消费者的变形,不能用一个信号量解决问题。在本题中,爸爸、儿子、女儿共用一个盘子,且盘中一次只能放一个水果。当盘子为空时,爸爸可将一个水果放入盘中,若放入采盘中的是苹果,则允许女儿吃,儿子必须等待。若放入盘中的是桔子,则允许儿子吃,女儿必须等待。
- 那么盘子就是一个缓冲区(单缓冲),同一时刻,只能有一个人对它进行放和取得操作。所以盘子就是一个互斥信号量。而盘子上有苹果,且父亲没有放,儿子才能取,女儿也是同理。所以应该还有两个资源信号量:1 苹果 2 桔子
- 在由题意分析可知,三个信号量的初始值应该为 1 0 0 因为桌子只能放一个水果。而在开始的时候,桌子上是空的(所以可以进行放的操作),所以苹果、桔子初始资源量都为空。
代码如下:
#include<iostream>
#include<windows.h>
using namespace std;
HANDLE g_apple = 0;//女儿线程互斥:表示可否取苹果
HANDLE g_orange = 0;//儿子线程互斥:表示可否取桔子
HANDLE g_hMutex = 0; //父亲线程互斥:表示可否向盘中放水果
bool g_continue = true; //控制程序运行和结束
DWORD WINAPI Father(LPVOID); //父亲线程
DWORD WINAPI Son(LPVOID);//儿子线程
DWORD WINAPI Daughter(LPVOID);//女儿线程
int main()
{
//创建各个信号量
g_orange = CreateSemaphore(NULL, 0, 1, NULL);
g_apple = CreateSemaphore(NULL, 0, 1, NULL);
g_hMutex = CreateSemaphore(NULL, 1, 1, NULL);
DWORD threadID[3];
HANDLE hThreads[3];
//创建父亲线程
hThreads[0] = CreateThread(NULL, 0, Father, NULL, 0, &threadID[0]);
if (hThreads == NULL) return -1;
//创建儿子线程
hThreads[1] = CreateThread(NULL, 0, Son, NULL, 0, &threadID[1]);
if (hThreads == NULL) return -1;
//创建女儿线程
hThreads[2] = CreateThread(NULL, 0, Daughter, NULL, 0, &threadID[2]);
if (hThreads == NULL) return -1;
while (g_continue){
if (getchar()){ //按回车后终止程序运行
g_continue = false;
}
}
return 0;
}
//父亲线程
DWORD WINAPI Father(LPVOID lpPara)
{
while (g_continue){
WaitForSingleObject(g_hMutex, INFINITE);
int m = rand() % 2;
if (m == 1) {
std::cerr << "父亲放入一个苹果!" << std::endl;
Sleep(1500);
ReleaseSemaphore(g_apple, 1, NULL);
}
else{
std::cerr << "父亲放入一个桔子!" << std::endl;
Sleep(1500);
ReleaseSemaphore(g_orange, 1, NULL);
}
}
return 0;
}
//女儿线程
DWORD WINAPI Daughter(LPVOID lpPara)
{
while (g_continue){
WaitForSingleObject(g_apple, INFINITE);
std::cerr << "女儿吃到一个苹果!" << std::endl;
Sleep(1500);
ReleaseSemaphore(g_hMutex, 1, NULL);
}
return 0;
}
//儿子线程
DWORD WINAPI Son(LPVOID lpPara)
{
while (g_continue){
WaitForSingleObject(g_orange, INFINITE);
std::cerr << "儿子吃到一个桔子!" << std::endl;
Sleep(1500);
ReleaseSemaphore(g_hMutex, 1, NULL);
}
return 0;
}
运行结果如下: