C++模拟“生产者消费者”进程同步问题

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <string>
#include <time.h>

using namespace std;

const int limit = 30;  //生产总量
const int maxsize = 10; //缓冲区大小
const int kind = 7;
int bufIdx = 0;    //当前缓冲区下标

string buf[maxsize];    //缓冲区 (字符串)

//伪造的产品
string product[] = {"Apple","Banana","Cherry","Orange","Pear","Peach","WaterMelon"};

HANDLE mutex,full,empty;

HANDLE disp;    //用于控制屏幕打印的互斥锁

//生产者子过程
DWORD WINAPI Producer(LPVOID param)
{
    int ct,idx;
    const int pwait = 100;
    srand(time(NULL)); //随机数播种

    WaitForSingleObject(disp, INFINITE);
    cout << "Producer Start!" << endl << endl;
    ReleaseMutex(disp);

	for (ct = 0; ct < limit; ct ++)
	{
	    idx = rand() % kind;

	    WaitForSingleObject(disp, INFINITE);
	    cout << product[idx] << " is ready!" << endl << endl;
	    ReleaseMutex(disp);

	    WaitForSingleObject(empty, INFINITE); //请求一个空缓冲区,阻塞
	    WaitForSingleObject(mutex, INFINITE); //请求互斥锁,阻塞
	    buf[bufIdx ++] = product[idx];

	    WaitForSingleObject(disp, INFINITE);
        cout << product[idx] << " added to slot No. " << bufIdx << endl << endl;
        ReleaseMutex(disp);

        ReleaseMutex(mutex);    //释放互斥锁
        ReleaseSemaphore (full, 1, NULL);   //signal(full)
        Sleep(rand() % pwait + 100);  //休息一会
	}
	cout << "Producer Quit!" << endl << endl;
	return 0;
}

//消费者子过程
DWORD WINAPI Consumer(LPVOID param)
{
    int ct;
    const int cwait = 300;
    string stuff;
    srand(time(NULL));

    WaitForSingleObject(disp, INFINITE);
    cout << "Consumer Start!" << endl << endl;
    ReleaseMutex(disp);

    for (ct = 0; ct < limit; ct ++)
	{
	    WaitForSingleObject(full, INFINITE); //请求一个满缓冲区,阻塞
	    WaitForSingleObject(mutex, INFINITE); //请求互斥锁,阻塞
	    stuff = buf[-- bufIdx];

        WaitForSingleObject(disp, INFINITE);
        cout << "Consumer get " << stuff << " from slot No. " << (bufIdx + 1) << endl << endl;
        ReleaseMutex(disp);

        ReleaseMutex(mutex);    //释放互斥锁
        ReleaseSemaphore (empty, 1, NULL);   //signal(empty)
        Sleep(rand() % cwait + 100);  //休息一会
	}
	cout << "Consumer Quit!" << endl << endl;
	return 0;
}

int main()
{
    //生产者线程与消费者线程的线程ID
	DWORD ProducerID, ConsumerID;
	//线程句柄
	HANDLE ProducerHandle, ConsumerHandle;

	//创建生产者线程
	ProducerHandle = CreateThread(NULL, 0, Producer, NULL, 0, &ProducerID);
	//创建消费者线程
	ConsumerHandle = CreateThread(NULL, 0, Consumer, NULL, 0, &ConsumerID);

    disp = CreateMutex(NULL, FALSE, NULL);
    //创建互斥锁
    mutex = CreateMutex(NULL, FALSE, NULL);
    //创建缓冲区占用信号量
    full = CreateSemaphore (NULL, 0, maxsize, "full");
    //创建缓冲区空闲信号量
    empty = CreateSemaphore (NULL, maxsize, maxsize, "empty");

    //等待直到生产者线程执行完成
	if (ProducerHandle != NULL)
	{
		WaitForSingleObject(ProducerHandle, INFINITE);
		CloseHandle(ProducerHandle);
	}
    //等待直到消费者线程执行完成
	if (ConsumerHandle != NULL)
	{
		WaitForSingleObject(ConsumerHandle, INFINITE);
		CloseHandle(ConsumerHandle);
	}
	system("pause");
}

1. 目的: 调试、修改、运行模拟程序,通过形象化的状态显示,使学生理解进程的概念,了解同步和通信的过程,掌握进程通信和同步的机制,特别是利用缓冲区进行同步和通信的过程。通过补充新功能,使学生能灵活运用相关知识,培养创新能力。 2. 内容及要求: 1) 调试、运行模拟程序。 2) 发现并修改程序中不完善的地方。 3) 修改程序,使用随机数控制创建生产者消费者的过程。 4) 在原来程序的基础上,加入缓冲区的写互斥控制功能,模拟多个进程存取一个公共缓冲区,当有进程正在写缓冲区时,其他要访问该缓冲区的进程必须等待,当有进程正在读取缓冲区时,其他要求读取的进程可以访问,而要求写的进程应该等待。 5) 完成1)、2)、3)功能的,得基本分,完成4)功能的加2分,有其它功能改进的再加2分 3. 程序说明:   本程序是模拟两个进程,生产者(producer)和消费者(Consumer)工作。生产者每次产生一个数据,送入缓冲区中。消费者每次从缓冲区中取走一个数据。缓冲区可以容纳8个数据。因为缓冲区是有限的,因此当其满了时生产者进程应该等待,而空时,消费者进程应该等待;当生产者向缓冲区放入了一个数据,应唤醒正在等待的消费者进程,同样,当消费者取走一个数据后,应唤醒正在等待的生产者进程。就是生产者消费者之间的同步。   每次写入和读出数据时,都将读和写指针加一。当读写指针同样时,又一起退回起点。当写指针指向最后时,生产者就等待。当读指针为零时,再次要读取的消费者也应该等待。 为简单起见,每次产生的数据为0-99的整数,从0开始,顺序递增。两个进程的调度是通过运行者使用键盘来实现的。 4. 程序使用的数据结构 进程控制块:包括进程名,进程状态和执行次数。 缓冲区:一个整数数组。 缓冲区说明块:包括类型,读指针,写指针,读等待指针和写等待指针。 5. 程序使用说明   启动程序后,如果使用'p'键则运行一次生产者进程,使用'c'键则运行一次消费者进程。通过屏幕可以观察到两个进程的状态和缓冲区变化的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值