操作系统-吸烟者问题(C++信号量实现)

    三个吸烟者在一个房间内,有一个香烟供应商.为了制造并抽烟,每个吸烟者必须具备:烟草、纸和火柴.
    三个吸烟者中,第一个有烟草,第二个有纸,第三个有火柴.供应者有丰富的货物,
    随机将两样东西放在桌子上名允许一个吸烟者进行对健康不利的吸烟.
    当吸烟者完成吸烟后唤醒供应者,供应者再把两样东西放在桌子上,唤醒另一个吸烟者.
    采用信号量编写他们同步工作的程序. 

  关系:吸烟者之间互斥,供应商与吸烟者同步

代码:

	/*
    Project:吸烟者问题
    Date:    2018/08/05
    Author:  Frank Yu
	三个吸烟者在一个房间内,有一个香烟供应商.为了制造并抽烟,每个吸烟者必须具备:烟草、纸和火柴.
	三个吸烟者中,第一个有烟草,第二个有纸,第三个有火柴.供应者有丰富的货物,
	随机将两样东西放在桌子上名允许一个吸烟者进行对健康不利的吸烟.
	当吸烟者完成吸烟后唤醒供应者,供应者再把两样东西放在桌子上,唤醒另一个吸烟者.
	采用信号量编写他们同步工作的程序.
*/
#include<iostream>
#include<string>
#include<algorithm>
#include<Windows.h> //多线程编程
#include<process.h>
using namespace std;
//变量声明初始化**********************************************************************************
 int randomnum=0;//随机数 
 HANDLE offer1,offer2,offer3;//三种材料的组合 纸和火柴 烟草和火柴 烟草和纸
 HANDLE finish; //吸烟者吸完烟信号
 //进程同步-供货商线程
unsigned __stdcall threadProvider(void *)
{
    for(int i = 0; ; i++){
		randomnum=rand()%3;//产生随机数
        if(randomnum==0) ReleaseSemaphore(offer1, 1, NULL);//提供组合1给吸烟者1
		else if(randomnum==1) ReleaseSemaphore(offer2, 1, NULL);//提供组合2给吸烟者2
		else ReleaseSemaphore(offer3, 1, NULL);//提供组合3给吸烟者3
		WaitForSingleObject(finish, INFINITE);//判断吸烟者是否吸完
    }
    return 1;
}
//进程同步-吸烟者1线程
unsigned __stdcall threadSmoker1(void *)
{
    for(int i = 0; ; i++){
        WaitForSingleObject(offer1, INFINITE);//获得材料组合1
        cout<<"吸烟者1在吸烟..."<<endl;
		Sleep(100);
		ReleaseSemaphore(finish, 1, NULL);//给提供商信号
    }
    return 2;
}
//进程同步-吸烟者2线程
unsigned __stdcall threadSmoker2(void *)
{
    for(int i = 0; ; i++){
        WaitForSingleObject(offer2, INFINITE);//获得材料组合2
        cout<<"吸烟者2在吸烟..."<<endl;
		Sleep(100);
		ReleaseSemaphore(finish, 1, NULL);//给提供商信号
    }
    return 3;
}
//进程同步-吸烟者3线程
unsigned __stdcall threadSmoker3(void *)
{
    for(int i = 0; ; i++){
        WaitForSingleObject(offer3, INFINITE);//获得材料组合3
        cout<<"吸烟者3在吸烟..."<<endl;
		Sleep(100);
		ReleaseSemaphore(finish, 1, NULL);//给提供商信号
    }
    return 4;
}
//算法及功能*********************************************************************
//吸烟者算法模拟
void process_Smoker()
{
    //创建信号量
    offer1 = CreateSemaphore(NULL, 0, 1, NULL);//材料组合1,初值为0,最大值为1
	offer2 = CreateSemaphore(NULL, 0, 1, NULL);//材料组合2,初值为0,最大值为1
	offer3 = CreateSemaphore(NULL, 0, 1, NULL);//材料组合3,初值为0,最大值为1
	finish = CreateSemaphore(NULL, 0, 1, NULL);//材料组合3,初值为0,最大值为1
    HANDLE hth1,hth2,hth3,hth4;                     //线程句柄
    //创建线程
    hth1 = (HANDLE)_beginthreadex(NULL, 0, threadProvider, NULL, 0, NULL);//供应商线程
    hth2 = (HANDLE)_beginthreadex(NULL, 0, threadSmoker1, NULL, 0, NULL);//吸烟者1线程
	hth3 = (HANDLE)_beginthreadex(NULL, 0, threadSmoker2, NULL, 0, NULL);//吸烟者2线程
	hth4 = (HANDLE)_beginthreadex(NULL, 0, threadSmoker3, NULL, 0, NULL);//吸烟者3线程
    //等待子线程结束
    WaitForSingleObject(hth1, INFINITE);
    WaitForSingleObject(hth2, INFINITE);
	WaitForSingleObject(hth3, INFINITE);
	WaitForSingleObject(hth4, INFINITE);
    //一定要记得关闭句柄
    CloseHandle(hth1);
    CloseHandle(hth2);
	CloseHandle(hth3);
	CloseHandle(hth4);
    CloseHandle(offer1);
	CloseHandle(offer2);
	CloseHandle(offer3);
	CloseHandle(finish);
}
//主函数*********************************************************************
int main()
{
	cout<<"*************欢迎进入吸烟者模拟程序****************"<<endl;
	process_Smoker();
 return 0;
}

结果截图:

吸烟者结果截图

有不懂函数参数的,看下面的文章:

操作系统-使用信号量实现生产者与消费者(C++实现)

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。 

吸烟者问题是经典的同步问题,在操作系统中常用信号量来解决。 在吸烟者问题中,有三个进程A、B、C分别代表三个吸烟者和一个代表桌子的服务进程D。这三个吸烟者分别需要不同的材料才能够吸烟,而桌子上只有三种材料中的两种,当满足某个吸烟者需要的两种材料时,他才能够拿到这两种材料进行吸烟。 信号量模拟算法如下: 1. 定义三个信号量:mutex、tobacco、paper、matches,初始值都为0。 2. 服务进程D执行如下循环: ``` while(true) { wait(mutex); // 等待其他进程释放mutex信号量 if(tobacco && paper) { // 如果桌子上有烟草和纸 tobacco = paper = 0; // 拿走烟草和纸 signal(matches); // 释放matches信号量 } else if(tobacco && matches) { // 如果桌子上有烟草和火柴 tobacco = matches = 0; // 拿走烟草和火柴 signal(paper); // 释放paper信号量 } else if(paper && matches) { // 如果桌子上有纸和火柴 paper = matches = 0; // 拿走纸和火柴 signal(tobacco); // 释放tobacco信号量 } signal(mutex); // 释放mutex信号量 } ``` 3. 三个吸烟者进程分别执行如下循环: ``` while(true) { wait(mutex); // 等待其他进程释放mutex信号量 if(hasTobacco && hasPaper) { // 如果拥有烟草和纸 hasTobacco = hasPaper = 0; // 拿走烟草和纸 signal(agent); // 通知服务进程D smoke(); // 吸烟 } else if(hasTobacco && hasMatches) { // 如果拥有烟草和火柴 hasTobacco = hasMatches = 0; // 拿走烟草和火柴 signal(agent); // 通知服务进程D smoke(); // 吸烟 } else if(hasPaper && hasMatches) { // 如果拥有纸和火柴 hasPaper = hasMatches = 0; // 拿走纸和火柴 signal(agent); // 通知服务进程D smoke(); // 吸烟 } else { signal(mutex); // 如果没有相应的材料,则释放mutex信号量 } } ``` 其中,hasTobacco、hasPaper、hasMatches分别表示三个吸烟者当前拥有的材料,smoke()函数表示吸烟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lady_killer9

感谢您的打赏,我会加倍努力!

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

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

打赏作者

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

抵扣说明:

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

余额充值