生产者与消费者实验报告

生产者消费者实验报告
【实验目的】
1.加深对进程概念的理解,明确进程和程序的区别。
2.进一步认识并发执行的实质。
3.验证用信号量机制实现进程互斥的方法。
同温同压下4.验证用信号量机制实现进程同步的方法。
【实验要求】
用c语言编程搭建“生产者和消费者”经典进程通信问题的环境。要求程序运行时,按任意键停止,显示当前系统的各个参数的值。提交实验报告,以及相关程序列表。打包成附件上传。
【实验环境】
Visual C++6.0
【实验内容】
1.了解经典同步问题“生产者和消费者”
生产者与消费者可以通过一个环形缓冲池联系起来,环形缓冲池由几个大小相等的缓冲块组成,每个缓冲块容纳一个产品。每个生产者可不断地每次往缓冲池中送一个生产产品,而每个消费者则可不断地每次从缓冲池中取出一个产品。指针i和指针j分别指出当前的第一个空缓冲块和第一个满缓冲块。
2.分析和理解
(1)既存在合作同步问题,也存在临界区互斥问题
增压供水合作同步:当缓冲池全满时,表示供过于求,生产者必须等待,同时唤醒消费者;当缓冲池全空时,表示供不应求,消费者应等待,同时唤醒生产者。
互斥:缓冲池显然是临界资源,所在生产者与消费都要使用它,而且都要改变它的状态。
(2)基于环形缓冲区的生产者与消费者关系形式描述:
公用信号量mutex:初值为1,用于实现临界区互斥
生产者私用信号量empty:初值为n,指示空缓冲块数目
消费者私用信号量full:初值为0,指示满缓冲块数目
整型量i和j初值为0,i指示首空缓冲块序号,j指示首满缓冲块序号
(3)PV原语
var mutex,empty,full:semaphore;
i,j:integer;buffer:-1] of item;
i:=j:=1;
Procedure producer;
begin
while true do
begin
produce a product;
P(empty);
P(mutex);
buffer(i):=product;
i:=(i+1) mod n;
V(mutex);
V(full);
end;
end;
Procedure consumer;
begin
P(full);
P(mutex);
goods:=buffer(j);
j:=(j+1) mod n;
V(mutex);
V(empty);
consume a product;
end;
end;
【实验源程序代码】
#include <windows.h>
#include <iostream>
const unsigned short SIZE_OF_BUFFER = 10;  //缓冲区长度
unsigned short ProductID = 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 Producer(LPVOID);      //生产者线程
DWORD WINAPI Consumer(LPVOID);    //消费者线程
int main()
{
    //创建各个互斥信号
    g_hMutex = CreateMutex(NULL,FALSE,NULL);
    g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,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;
    HANDLE hThreads[PRODUCERS_COUNT];    //各线程的handle
    DWORD producerID[CONSUMERS_COUNT];  //生产者线程的标识符
    DWORD consumerID[THREADS_COUNT];  //消费者线程的标识符
    //创建生产者线程
    for (int i=0;i<PRODUCERS_COUNT;++i){金属检测传感器
        hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);
        if (hThreads[i]==NULL) return -1;
    }
    //创建消费者线程
    for (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 Produce()
{
    std::cerr << "Producing " << ++ProductID << " ... ";
    std::cerr << "Succeed" << std::endl;
}
//把新生产的产品放入缓冲区
void Append()
{
    std::cerr << "Appending a product ... ";
    g_buffer[in] = ProductID;
    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 product ... ";
    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 Producer(LPVOID lpPara)
{
    while(g_continue){
        WaitForSingleObject(g_hFullSemaphore,INFINITE);
棉花糖机械
        WaitForSingleObject(g_hMutex,INFINITE);
        Produce();
        Append();
        Sleep(1500);
        ReleaseMutex(g_hMutex);
        ReleaseSemaphore(g_hEmptySemaphore,1,NULL);
    }
sync pad    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;
}
【实验结果】
具体程序见附件(网络查)
【实验反思】
本次实验是关于生产者和消费者之间互斥和同步的问题。问题的实质是P,V操作,实验设一个共享缓冲区,生产者和消费者互斥的使用,当一个线程使用缓冲区的时候,另一个让其等待知道前一个线程释放缓冲区为止。
  通过本次实验,我们对操作系统的P,V进一步的认识,深入的了解P,V操作的实质和其重要性。课本的理论知识进一步阐述了现实的实际问题。
 
【实验思考题】
1.思考在“生产者和消费者”经典同步问题中,两个P操作是否可以互换位置,以及两个V操作是否可以互换位置。

本文发布于:2024-09-23 08:17:41,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/127219.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:生产者   消费者   缓冲区   缓冲   问题   实验   产品   线程
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议