问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

操作系统中的信号量机制问题

发布网友 发布时间:2022-03-30 01:21

我来回答

1个回答

热心网友 时间:2022-03-30 02:51

一、问题描述

生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。
他要求设计在同一个进程地址空间内执行的两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

同理 本问题也是要求设计在同一个进程地址空间内执行的两个线程。
当车站售票厅达到20人上线时,必须等有人走出车站售票厅,车站售票厅外的购票者才可进入。就如上面
生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。此时厅外购票者进入大厅这个事件可以看做是一个生产者线程,而厅内购票者走出厅外这个事件就可以看做是一个消费者线程。如此问题迎刃而解。

二、实现代码

#include <windows.h>
#include <iostream>

const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度
unsigned short ProctID = 0; //产品号
unsigned short ConsumeID = 0; //将被消耗的产品号
unsigned short in = 0; //产品进缓冲区时的缓冲区下标
unsigned short out = 0; //产品出缓冲区时的缓冲区下标

int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列
bool g_continue = true; //控制程序结束
HANDLE g_hMutex; //用于线程间的互斥
HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待
HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待

DWORD WINAPI Procer(LPVOID); //生产者线程
DWORD WINAPI Consumer(LPVOID); //消费者线程

int main()
{
//创建各个互斥信号
g_hMutex = CreateMutex(NULL,FALSE,NULL);
g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);

//调整下面的数值,可以发现,当生产者个数多于消费者个数时,
//生产速度快,生产者经常等待消费者;反之,消费者经常等待
const unsigned short PRODUCERS_COUNT = 3; //生产者的个数
const unsigned short CONSUMERS_COUNT = 1; //消费者的个数

//总的线程数
const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;

DWORD procerID[CONSUMERS_COUNT]; //生产者线程的标识符
DWORD consumerID[THREADS_COUNT]; //消费者线程的标识符

//创建生产者线程
for (int i=0;i<PRODUCERS_COUNT;++i){
hThreads[i]=CreateThread(NULL,0,Procer,NULL,0,&procerID[i]);
if (hThreads[i]==NULL) return -1;
}
//创建消费者线程
for (int i=0;i<CONSUMERS_COUNT;++i){
hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);
if (hThreads[i]==NULL) return -1;
}

while(g_continue){
if(getchar()){ //按回车后终止程序运行
g_continue = false;
}
}

return 0;
}

//生产一个产品。简单模拟了一下,仅输出新产品的ID号
void Proce()
{
std::cerr << "Procing " << ++ProctID << " ... ";
std::cerr << "Succeed" << std::endl;
}

//把新生产的产品放入缓冲区
void Append()
{
std::cerr << "Appending a proct ... ";
g_buffer[in] = ProctID;
in = (in+1)%SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;

//输出缓冲区当前的状态
for (int i=0;i<SIZE_OF_BUFFER;++i){
std::cout << i <<": " << g_buffer[i];
if (i==in) std::cout << " <-- 生产";
if (i==out) std::cout << " <-- 消费";
std::cout << std::endl;
}
}

//从缓冲区中取出一个产品
void Take()
{
std::cerr << "Taking a proct ... ";
ConsumeID = g_buffer[out];
out = (out+1)%SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;

//输出缓冲区当前的状态
for (int i=0;i<SIZE_OF_BUFFER;++i){
std::cout << i <<": " << g_buffer[i];
if (i==in) std::cout << " <-- 生产";
if (i==out) std::cout << " <-- 消费";
std::cout << std::endl;
}
}

//消耗一个产品
void Consume()
{
std::cerr << "Consuming " << ConsumeID << " ... ";
std::cerr << "Succeed" << std::endl;
}

//生产者
DWORD WINAPI Procer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hFullSemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Proce();
Append();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hEmptySemaphore,1,NULL);
}
return 0;
}

//消费者
DWORD WINAPI Consumer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hEmptySemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Take();
Consume();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hFullSemaphore,1,NULL);
}
return 0;
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
有机物的概念是什么? 百度账号无法登陆,总是提示登陆超时,区稍后再试。手机可以登陆,就是... 电脑百度账号登录,总提示超时,网上不少经验都试了还不行!谁还有新... 为什么我家电脑登不上百度贴吧登的时候总是显示登录超时,可网速... 无法登陆百度,显示登陆超时。。 为什么电脑登陆百度总是超时? 怎么样把监控录像里面的场景弄清晰点 学校校园宽带怎么改密码? 学校里的wifi,自己设置的密码,忘记了怎么办 大学宽带密码忘记了怎么办 快手小店最多可以添加多少个商品呢? 快手小店商品顺序号怎么设置 快手小店电商商品暂时无法编辑怎么弄 快手小店怎么添加商品?上架商品到小店哪个工具好? 快手小店暂时不支持多级规格和名称修改和新增怎么回事 快手小店规格值是什么意思 快手小店商品添加,规格栏里鞋的尺码填不下怎么办? 期货盈亏如何计算? 期货平仓盈亏怎么计算 期货平仓盈亏问题 关于期货平仓盈亏计算的问题,求解. 持仓盈亏是什么意思 期货上平仓盈亏怎么计算啊 Linux信号 机制和Linux信号量机制的区别 期货盈亏如何计算? 期货盈亏怎么算?爆仓是什么? 机构持仓盈亏比是什么意思 期货的平仓盈亏(盯 ,浮)什么意思 期货平仓是什么意思 五大银行利率三年多少2020? 路由器只需接网线也可以开WIFI吗? 把网线直接插在路由器上,不用电脑,能用wifi吗? 直接把网线插到路由器上是不是也可以连接wifi 网线直接插路由器可以发射wifi信号吗? 路由器一端连网线,还可以连wifi吗 从路由器接出来的网线可以弄无线网络吗 只有网线和路由器可以用wifi吗? 无线路由器如何插网线就可以连接Wi-Fi 家里没电脑 网线直接插在路由器上 可以连WiFi上网吗 无线路由器是不是直接接到网线上就可以用了? wifi是不是用一个无线路由器接上网线就可以用了 只有网线和路由器可以用wifi吗 为什么无线路由器电脑连接能上网,手机连接上了却不能上网? 一根网线怎么连接WIFI无线!有路由器 无线路由器直接连接网线怎么设置 无线路由器直接接网线可以吗? 网线直接连接无线路由器设置 信号量机制是为了解决什么问题而设置的 佳能ir2520i打印机驱动怎么安装 佳能家用打印机打印方法