桌上有一空盘,最多允许存放一只水果。爸爸可向盘中放一个苹果或放一个桔子,儿子专等吃盘中的桔子,女儿专等吃苹果。
试用P、V操作实现爸爸、儿子、女儿三个并发进程的同步。
提示:设置一个信号量表示可否向盘中放水果,一个信号量表示可否取桔子,一个信号量表示可否取苹果。
实验目的:
深入掌握进程、线程同步机制——信号量机制的原理与应用;
掌握Windows编程中信号量机制的使用方法;
掌握Windows下线程的控制方法;
可进行简单的信号量应用编程。
下面展示一些 内联代码片
。
从这个题意可以得出,这个实验一共有3个进程,
分别是父亲,儿子,女儿。
且要设置3个信号量,
S:表示是否可以向盘子防水果 初值为1 表示盘子为空
S0:表示盘子中放的是桔子 初值为0 表示盘子内不是桔子
S1:表示盘子中放的是苹果 初值为0 表示盘子内不是苹果
// 进行P,V操作(P,V操作为原子操作不可被打断)
//父亲
father()
{ while(1){
P(S);//申请盘子的使用权
将水果放入盘中
if(是桔子){
V(S0);//释放是桔子的信号量,S0+1)
}
else{
V(S1);//释放是苹果的信号量,S1+1)
}
}
}
//儿子
son()
{while(1){
p(S0);//等待盘子中是桔子的信号
取桔子;
V(S);释放盘子的使用权
吃桔子;
}
}
//女儿
daughter()
{while(1){
p(S1);//等待盘子中是苹果的信号
取苹果;
V(S);释放盘子的使用权
吃苹果;
}
}
#include <windows.h>
#include <iostream>
#include<stdio.h>
bool g_continue = true; //控制程序结束
HANDLE g_hS; //当盘子为空时的线程
HANDLE g_hS0; //当盘子中放的是桔子线程
HANDLE g_hS1; //当盘子中放的是苹果线程
DWORD WINAPI father(LPVOID); //定义父亲线程
DWORD WINAPI son(LPVOID); //定义儿子线程
DWORD WINAPI daughter(LPVOID);//定义女儿线程
int main()
{
//创建各个互斥与资源信号量
g_hS = CreateSemaphore(NULL,1,1,NULL); //盘子中是否有水果
g_hS0 = CreateSemaphore(NULL,0,1,NULL); //盘子中的水果为桔子
g_hS1 = CreateSemaphore(NULL,0,1,NULL); //盘子中的水果为苹果
//其中第2和3个参数为信号量的初始值和最大值
const unsigned short father_COUNT = 0; //声明父亲
const unsigned short son_COUNT = 0; //声明儿子
const unsigned short daughter_COUNT = 0;//声明女儿
//总的线程数
const unsigned short THREADS_COUNT = father_COUNT+son_COUNT+daughter_COUNT ;
HANDLE hThreads[THREADS_COUNT]; //各线程的handle
DWORD fatherID[father_COUNT]; //父亲线程的标识符
DWORD sonID[son_COUNT]; //儿子线程的标识符
DWORD daughterID[daughter_COUNT]; //女儿线程的标识符
//创建父亲进程
hThreads[0]=CreateThread(NULL,0,father,NULL,0,&fatherID[0]);
if (hThreads[0]==NULL) return -1;
//创建儿子进程
hThreads[1]=CreateThread(NULL,0,son,NULL,0,&sonID[0]);
if (hThreads[1]==NULL) return -1;
//创建女儿进程
hThreads[2]=CreateThread(NULL,0,daughter,NULL,0,&daughterID[0]);
if (hThreads[2]==NULL) return -1;
while(g_continue){
if(getchar()){ //按回车后终止程序运行
g_continue = false;
}
}
return 0;
}
//父亲放水果的操作,输出
void eat()
{
std::cerr << "儿子吃桔子" << std::endl;
}
void eat1()
{
std::cerr << "女儿吃苹果" << std::endl;
}
//父亲进程
DWORD WINAPI father(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hS,INFINITE);
int juzhi=rand()%2; //设置了一个随机数,来模拟父亲放的是什么水果
Sleep(1500);//方便观察实验结果
if(juzhi==1){
printf("父亲放入了一个桔子\n");
Sleep(1000);
ReleaseSemaphore(g_hS0,1,NULL);
}
else{
printf("父亲放入了一个苹果\n");
Sleep(1000);
ReleaseSemaphore(g_hS1,1,NULL);
}
}
return 0;
}
//儿子进程
DWORD WINAPI son(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hS0,INFINITE);
eat();
Sleep(1500);
ReleaseSemaphore(g_hS,1,NULL);
}
return 0;
}
//女儿进程
DWORD WINAPI daughter(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hS1,INFINITE);
eat1();
Sleep(1500);
ReleaseSemaphore(g_hS,1,NULL);
}
return 0;
}