【操作系统】互斥与同步,吃水果,吃巧克力问题(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丈夫算法流程图

在这里插入图片描述
图3-2 父亲算法流程图

3.4妻子算法流程图

在这里插入图片描述
图3-3 母亲算法流程图

3.5小狗算法流程图

在这里插入图片描述
图3-3 小狗算法流程图

3.6小猫算法流程图

在这里插入图片描述
图3-3 小猫算法流程图

四、源代码(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;  
}

  • 11
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码两年半的练习生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值