福建农林大学金山学院实验报告
系(教研室): 信息与机电工程系 专业: 计算机科学与技术 年级: 2014 实验课程: 生产者与消费者实验 姓名: 蒲志遥 学号: 146709026 实验室号:1#604 计算机号: 056 实验时间: 2016.11.14 指导教师签字: 成绩: 实验1:生产者消费者问题
一、 实验目的
生产者消费者问题是操作系统中经典的同步和互斥问题。通过实验,要求学生掌握两者之间的同步信号量和互斥信号量的使用,更深刻了解临界资源、同步和互斥的概念。
二、 实验要求
一组生产者通过一个具有N个缓冲区的缓冲池循环不断地向一组消费者提供产品。
建一个队列, 队列的长度由n记录, 定义两个指针, 分别指向队列的头和尾消费者从头指针读取数据,每读取一个数据把n--, 生产者把数据写入尾指针, 每写入一个数据就n++,当n=N的时候生产者暂停写入数据。
注意:缓冲池队列,用互斥锁保护。
三、 实验内容和原理
1.分别画出生产者和消费者的流程图
生产一条数据 是否有空缓冲区 阻塞,等待资源 被唤醒 是否可用 阻塞,等待使用权 被唤醒 存入一条数据 归还使用权 数据单元+1,唤醒消费者
是否有数据单元 阻塞,等待资源 被唤醒 是否可用 阻塞,等待使用权 被唤醒 取一条数据 归还使用权 空单元+1,唤醒生产者 消费数据
2. 针对生产者和消费者问题,可以分为哪几种情况,使用了哪些原语?分别代表什么意思?过程如何?阐述哪些进程之间存在同步,哪些进程之间存在互斥。
分为3种情况:1个生产者,一个消费者,一个缓冲区 1个生产者,一个消费者,多个缓冲区 多个生产者,多个消费者,多个缓冲区 有2个原语: wait申请资源 signal 释放资源 wait(empty); wait(mutex); buffer[in]=nextp; in=(in+1)%n; signal(mutex); signal(full);
存在同步:生产者和消费者 存在互斥: 生产者和消费者 生产者和生产者 消费者和消费者
3.缓冲区是否为临界资源?是否可以循环使用?通过什么来实现?举例说明(可画图)
缓冲区是临界资源,可以循环使用。通过循环缓冲池实现。
0
in 5 out 4
3
1 2 四、 实验环境
1. 硬件:PC机;
2. 软件:Windows操作系统、VC6.0。
五、 算法描述及实验步骤 六、 调试过程
不会终止程序。
七、 实验结果
七、总结
通过本次上机关于生产者消费者问题是操作系统中经典的同步和互斥问题。打代码中出现了
很多错误,还需要改进,代码是死循环不知道怎么终止。我还有很多不足还要好好学习。
附录:
#include #include 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]; DWORD producerID[CONSUMERS_COUNT]; DWORD consumerID[THREADS_COUNT];
for (int i=0;ihThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]); if (hThreads[i]==NULL) return -1; }for ( i=0;ihThreads[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; }
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;ivoid 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;ivoid 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); }
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; }