实验内容
在 windows 环境下,利用高级语言编程环境(限定为 VS 环境或 VC 环境) 调用 CreateThread 函数和相关的同步函数,模拟实现“生产者-消费者”问题。
实验过程
首先,先写个生成随机数的函数,代码如下:
int random(void){
int a=time (NULL);
srand(a);
return rand()%1000;
}
然后,是生产者的功能函数,主要代码如下:
if(id == 1) number = random()+1000;
else number = random()+2000;
Buffer[rear]=number;
printf("生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
rear = (rear+1)%N;
Sleep(600);
之后,需要加入pv操作以及临界区。这也是本题的难点所在。下面介绍windows环境是如何实现这些操作的。
临界区
Windows有专门的临界区对象。其应用也非常简单。如下:
CRITICAL_SECTION cs; //声明临界区对象
InitializeCriticalSection(&cs); //初始化临界区对象
EnterCriticalSection(&cs); //进入临界区
LeaveCriticalSection(&cs); //离开临界区
信号量机制
Windows通过信号量机制来实现p操作和v操作。其应用函数如下:
HANDLE full =NULL; //声明
full = CreateSemaphore(NULL ,0 ,N,"full"); //创建
CloseHandle(full); //关闭
HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full"); //打开
WaitForSingleObject(full,INFINITE); //p操作
ReleaseSemaphore(empty,1,NULL); //v操作
在这些函数中
CreateSemaphore(NULL ,0 ,N,“full”)函数的第二个参数是信号量的初始值,应大于等于0;第三个参数为信号量的最大值,第四个参数为信号量的名称(可用于在其他地方打开该信号量)。
ReleaseSemaphore(empty,1,NULL)函数的第二个参数代表释放之后信号量的值加n。
了解了windows的临界区对象和信号量机制之后,我们就可以理解生产者功能函数加入这两者之后的代码了:
DWORD WINAPI Producer(LPVOID lpParam){
int number;
int id = ++i;
HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");
HANDLE empty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"empty");
while(1){
if(id == 1) number = random()+1000;
else number = random()+2000;
//p(empty)
WaitForSingleObject(empty,INFINITE);
EnterCriticalSection(&cs);
Buffer[rear]=number;
printf("生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
flag++;
if(!flag){
fp=fopen("C:\\Users\\HP\\Desktop\\记录.txt","w");
if(fp==NULL){
printf("can not load file!");
exit(0);
}
}
fprintf(fp,"生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
rear = (rear+1)%N;
LeaveCriticalSection(&cs);
//v(full)
ReleaseSemaphore(full,1,NULL);
Sleep(600);
}
}
以同样的方式,我们可以写出消费者的功能函数,然后再在主函数中用CreateThread调用这两个子程序,生成多线程。
完整代码:
#include <stdio.h>
#include <windows.h>
#include <time.h>
#define N 10
FILE *fp=NULL;
int flag = -1;
int Buffer[N];
int front=0,rear=0,i=0,j=0;
CRITICAL_SECTION cs;
int random(void){
int a=time (NULL);
srand(a);
return rand()%1000;
}
//子线程函数
DWORD WINAPI Producer(LPVOID lpParam){
int number;
int id = ++i;
HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");
HANDLE empty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"empty");
while(1){
if(id == 1) number = random()+1000;
else number = random()+2000;
//p(empty)
WaitForSingleObject(empty,INFINITE);
EnterCriticalSection(&cs);
Buffer[rear]=number;
printf("生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
flag++;
if(!flag){
fp=fopen("C:\\Users\\HP\\Desktop\\记录.txt","w");
if(fp==NULL){
printf("can not load file!");
exit(0);
}
}
fprintf(fp,"生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
rear = (rear+1)%N;
LeaveCriticalSection(&cs);
//v(full)
ReleaseSemaphore(full,1,NULL);
Sleep(600);
}
}
//子线程函数
DWORD WINAPI Consumer(LPVOID lpParam){
int id = ++j;
HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");
HANDLE empty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"empty");
while(1){
//p(full)
WaitForSingleObject(full,INFINITE);
EnterCriticalSection(&cs);
printf("\t消费者%d消费Buffer[%d],%d\n",id,front,Buffer[front]);
flag++;
if(!flag){
fp=fopen("C:\\Users\\HP\\Desktop\\记录.txt","w");
if(fp==NULL){
printf("can not load file!");
exit(0);
}
}
fprintf(fp,"\t消费者%d消费Buffer[%d],%d\n",id,front,Buffer[front]);
front = (front+1)%N;
LeaveCriticalSection(&cs);
//v(empty)
ReleaseSemaphore(empty,1,NULL);
Sleep(1000);
}
}
//主函数
int main(){
InitializeCriticalSection(&cs); //初始化临界区对象
HANDLE full =NULL;
full = CreateSemaphore(NULL ,0 ,N,"full");
HANDLE empty =NULL;
empty = CreateSemaphore(NULL ,N,N,"empty");
HANDLE hThread[5];
hThread[0] = CreateThread(NULL,0,Producer,NULL,0,NULL);
hThread[1] = CreateThread(NULL,0,Producer,NULL,0,NULL);
hThread[2] = CreateThread(NULL,0,Consumer,NULL,0,NULL);
hThread[3] = CreateThread(NULL,0,Consumer,NULL,0,NULL);
hThread[4] = CreateThread(NULL,0,Consumer,NULL,0,NULL);
WaitForMultipleObjects(5,hThread,TRUE,10000); //等待子线程运行
fclose(fp);
CloseHandle(full);
CloseHandle(empty);
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)