学生姓名:
班 学 号:193121 指导教师:袁国斌
中国地质大学计算机学院 2013年 12 月 4 日 操作系统课程实验报告 实习题目:基于Windows进程互斥实现机制
【需求规格说明】
基于Microsoft Visual Studio环境的多线程编程验证互斥的原理,理解多线程编程中关键元素的定义与使用,通过使用Semaphore,mutex等控制元素,实现对生产者消费者模型的真实模拟。函数的功能与实现自己定义。
【算法设计】
(1) 设计思想:
通过输入生产者消费者数量信息,以及缓冲区大小、循环次数来实现对生产者消费者模型的真实模拟。当缓冲区Buffer为空时,等待生产者生产,消费者停止消费;当缓冲区Buffer为满时,等待消费者消费,生产者停止生产。
(2) 设计表示:
用Buffer_Size 定义缓冲区大小 用变量Thread[]数组来存储线程
使用函数调用ProducerPrintf()来输出生产的情况 使用函数调用ConsumerPrintf()来输出正在消费的情况 通过如下同步对象实现互斥:
设一个互斥量Mutex,实现生产者在查询和保留缓冲区的下一个空位置时进行互斥。
设置Semaphore信号量数组表示相应产品已经生产,实现生产者与消费者之间的同步。同时,用表示空缓冲区树木的信号量semephore指示是否存在空位置,实现类似的同步,以便开始下一个产品的生产。 设置临界区对象数组Critical实现每个缓冲区上消费者之间的互斥
(3) 详细设计表示:
主要过程:
1.主函数
2.输入并读取消费者生产者数量信息 3.输入缓冲区大小及循环操作次数
4.创建生产线程和消费线程完成线程相关同步对象的初始化 5.创建线程,模拟生产者和消费者 6.等待所有线程结束 7.程序结束
消费者线程:
1.有无消费请求?有,则继续,无,则结束 2.进入临界区(请求同一产品的消费者之间互斥) 3.消费产品,并判断是否应该释放产品所占缓冲区 4.退出临界区 5.结束消费者线程
生产者线程:
1.存在空缓冲区?有,则继续;无,则阻塞退出 2.进入临界区(请求同一产品的生产者之间互斥) 3.在缓冲区中为本线程产品分配空间 4.退出临界区
5.写入产品到分配的缓冲区空间中 6.结束生产者线程
【调试报告】
、
【附录】
#include #include #include #include #define N 40
int NUM=0; //定义缓冲区中产品数量的变量 int P_NUM=1; //生产次数计数
int C_NUM=1; //消费次数计数 int times=0; //循环次数
int Buffer_Size=0; //定义缓冲区大小的变量
HANDLE Mutex; //互斥信号量
HANDLE FullSemaphore; //当缓冲区满是使生产者等待 HANDLE EmptySemaphore; //当缓冲区空时使消费者等待 HANDLE Thread[N]; //存储线程的数组
DWORD WINAPI producer(LPVOID); DWORD WINAPI consumer(LPVOID); DWORD Producer_ID[N/2]; DWORD Consumer_ID[N/2];
void ProducerPrintf(); //输出生产的情况 void ConsumerPrintf(); //输出正在消费的情况
void main() { int i=1; int P_thread=0,C_thread=0; //定义线程变量
int choice=0; printf(\"\\t*****************************************\\n\"); printf(\"\\t*\\t欢迎进入P-C进程调度系统 *\\n\"); printf(\"\\t*\\t
1、进入模拟调度 *\\n\"); printf(\"\\t*\\t 0、退出本系统 *\\n\"); printf(\"\\t*****************************************\\n\"); printf(\"\\t\\t请选择:\");
//创建生产线程和消费线程 for(i=0;i
//创建信号量
Mutex=CreateMutex(NULL,FALSE,NULL); FullSemaphore=CreateSemaphore(NULL,Buffer_Size-1,Buffer_Size-1,NULL); EmptySemaphore=CreateSemaphore(NULL,0,Buffer_Size,NULL); WaitForMultipleObjects(P_thread+C_thread,Thread,TRUE,INFINITE); //while(P_NUM
1、请输入生产者线程数量:\"); scanf(\"%d\",&P_thread); printf(\"\\t\\t
2、请输入消费者线程数量:\"); scanf(\"%d\",&C_thread); printf(\"\\t\\t
3、请输入缓冲区的大小:\"); scanf(\"%d\",&Buffer_Size); scanf(\"%d\",×); printf(\"\\t*****************************************\\n\"); printf(\"\\t\\t生产消费情况如下\"); scanf(\"%d\",&choice); //输入生产和消费线程的数量以及缓冲区的大小、循环操作次数
printf(\"\\t\\t
4、请输入循环操作次数:\"); break; } DWORD WINAPI producer(LPVOID lpParameter) {
}
DWORD WINAPI consumer(LPVOID lpParameter) {
}
void ProducerPrintf() { int i=0; { if(P_NUM
for(i=1;i
if(P_NUM==P_NUM-NUM+i) printf(\"(%d)\",P_NUM-NUM+i); printf(\"%d \",P_NUM-NUM+i); else printf(\"
} return 0; WaitForSingleObject(EmptySemaphore,INFINITE); WaitForSingleObject(Mutex,INFINITE); ConsumerPrintf(); Sleep(500); ReleaseMutex(Mutex); ReleaseSemaphore(FullSemaphore,1,NULL); while(P_NUM
} return 0; WaitForSingleObject(FullSemaphore,INFINITE); WaitForSingleObject(Mutex,INFINITE); ProducerPrintf(); Sleep(500); //设置延迟时间 ReleaseMutex(Mutex); //释放互斥信号量 ReleaseSemaphore(EmptySemaphore,1,NULL); //释放信号量 }
} P_NUM++; } void ConsumerPrintf() {
} int i=0; { NUM--; printf(\"\\n消费者正在消费\\n\"); for(i=0;i
if(C_NUM==C_NUM+i) printf(\"