用多线程同步方法解决生产者消费者问题.docx
《用多线程同步方法解决生产者消费者问题.docx》由会员分享,可在线阅读,更多相关《用多线程同步方法解决生产者消费者问题.docx(14页珍藏版)》请在冰豆网上搜索。
用多线程同步方法解决生产者消费者问题
武汉理工大学华夏学院
课程设计报告书
课程名称:
操作系统原理
题目:
用多线程同步方法解决生产者-消费者问题
系名:
信息工程系
专业班级:
姓名:
学号:
指导教师:
年月日
课程设计任务书
学生姓名:
专业班级:
指导教师:
工作单位:
设计题目:
用多线程同步方法解决生产者-消费者问题
初始条件:
Linux操作系统,GCC编译环境
要求完成的主要任务:
主要任务:
通过研究Linux的线程机制和信号量实现生产者消费者问题的并发控制。
有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1~20这20个整型数。
(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。
(2)生产者和消费者各有两个以上。
(3)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。
提示:
(1)有界缓冲区/连续存储区可用数组实现。
(2)编译命令可用:
gcc-lpthread-o 目标文件名 源文件名
(3)多线程编程方法参见电子文档。
设计报告撰写格式要求:
1设计题目与要求2设计思想
3系统结构4数据结构的说明和模块的算法流程图
5使用说明书(即用户手册):
内容包含如何登录、退出、读、写等操作说明
6运行结果和结果分析(其中包括实验的检查结果、程序的运行情况)
7自我评价与总结
8附录:
程序清单,注意加注释(包括关键字、方法、变量等),在每个模块前加注释;时间安排
6月20日布置课程设计任务;分配题目后,查阅资料、准备程序;
6月21~6月23日上机调试程序、书写课程设计报告;
6月24日提交课程设计报告及相关文档。
指导教师签字:
2011年6月18日
系主任签字:
2011年6月19日
1.设计目的与要求
1.1设计目的
通过研究Linux的线程机制和信号量实现生产者消费者问题(Producer-ConsumerProblem)的并发控制。
1.2设计要求
1)为每个生产者/消费者产生一个线程,设计正确的同步算法
2)每个生产者/消费者对该存储区进行操作后,即时显示该存储区的全部内容、当
前指针位置和生产者/消费者线程的自定义标识符。
3)生产者和消费者各有两个以上。
4)多个生产者/消费者之间须共享对存储区进行操作的函数代码。
2.设计思想及系统平台
2.1设计思想
在本问题中,共需要一个Mutex和两个Semaphore.
其中,Mutex是用来锁定临界区的,以解决对共享数据buffer的互斥访问问题(无论是对生成者还是对消费者);
我们共需要两个Semaphore,这是因为在本问题中共有两个稀缺资源.
第一种是"非空"这种资源,是在消费者之间进行竞争的.
第二种是"非满"这种资源,是在生产者之间进行竞争的.
所以,一般来说,需要锁定临界区,就需要Mutex;有几种稀缺资源就需要几个Semaphore.
对稀缺资源的分析不能想当然.稀缺资源不一定是指被共享的资源,很多时候是指线程会被阻塞的条件(除了要进临界区被阻塞外).
在生产者消费者问题中,消费者会在缓冲区为空时被阻塞,所以"非空"是一种稀缺资源;
需要设置一个信号量consumer_semaphore,初值设为0;
生产者会在缓冲区为满时被阻塞,所以"非满"也是一种稀缺资源.
需要设置一个信号量producer_semaphore,初值设为buffer的大小MAX_BUFFER
2.2系统平台及使用语言
本课程设计在Linux操作系统下,使用C语言完成。
用到的工具主要有GCC编译器和VI编辑器。
3.详细算法描述
共享数据:
Semaphorebuffer_mutex=1;
Semaphoreproducer_semaphore=MAX_BUFFER;
Semaphoreconsumer_semaphore=0;
intbuffer[MAX_BUFFER];
Producer线程的处理函数:
while
(1){
Wait(producer_semaphore);
Wait(buffer_mutex);
Buffer[pn]=product;
pn=(pn+1)%MAX_BUFFER;
Signal(consumer_semaphore);
Signal(buffer_mutex);
Sleep();
}
producer线程的处理函数流程图如下:
consumer线程的处理函数:
while
(1){
Wait(consumer_semaphore);
Wait(buffer_mutex);
Consume=buffer[cn];
cn=(cn+1)%MAX_BUFFER;
Signal(producer_semaphore);
Signal(buffer_mutex);
Sleep();
}
consumer线程的处理函数流程图如下:
4.源程序清单(注释是后加上的)
用户名:
rj070126(IP:
192.168.2.254)
源程序名:
/home/rj070126/pc.c
目标程序名:
/home/rj070126/pc
运行结果:
/home/rj070126/output.txt
源程序清单如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineNUM_THREADS_P5/*定义数据为生产者*/
#defineNUM_THREADS_C5/*定义数据为消费者*/
#defineMAX_BUFFER20/*定义数据为缓存区*/
#defineRUN_TIME20/*定义运行时间*/
intbuffer[MAX_BUFFER];
intproduce_pointer=0,consume_pointer=0;
sem_tproducer_semaphore,consumer_semaphore,buffer_mutex;
pthread_tthreads_p[NUM_THREADS_P];/*声明生产者线程*/
pthread_tthreads_c[NUM_THREADS_C];/*声明消费者线程*/
FILE*fd;
void*producer_thread(void*tid);
void*consumer_thread(void*tid);
voidshowbuf();
voidhandler(){
inti;
for(i=0;ipthread_cancel(threads_p[i]);
for(i=0;ipthread_cancel(threads_c[i]);
}
intmain(){
inti;
signal(SIGALRM,handler);
fd=fopen("output.txt","w");/*打开一个文件用来保存结果*/
sem_init(&producer_semaphore,0,MAX_BUFFER);/*放一个值给信号灯*/
sem_init(&consumer_semaphore,0,0);
sem_init(&buffer_mutex,0,1);
for(i=0;ibuffer[i]=0;/*引发缓冲*/
/*创建线程*/
for(i=0;ipthread_create(&threads_p[i],NULL,(void*)producer_thread,(void*)(i+1));
for(i=0;ipthread_create(&threads_c[i],NULL,(void*)consumer_thread,(void*)(i+1));
alarm(RUN_TIME);
/*等待线程退出*/
for(i=0;ipthread_join(threads_p[i],NULL);
for(i=0;ipthread_join(threads_c[i],NULL);
/*清除信号灯*/
sem_destroy(&producer_semaphore);
sem_destroy(&consumer_semaphore);
sem_destroy(&buffer_mutex);
fclose(fd);
return0;
}
void*producer_thread(void*tid){
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
while
(1){
sem_wait(&producer_semaphore);
srand((int)time(NULL)*(int)tid);
sleep(rand()%2+1);/*一个或两个需要生产*/
while((produce_pointer+1)%20==consume_pointer);
sem_wait(&buffer_mutex);
buffer[produce_pointer]=rand()%20+1;
produce_pointer=(produce_pointer+1)%20;
if(produce_pointer==0){
printf("producer:
%dpointer_p:
%2dproduced:
%2d\n",(int)tid,19,buffer[19]);
fprintf(fd,"producer:
%dpointer_p:
%2dproduced:
%2d\n",(int)tid,19,buffer[19]);
}
else{
printf("producer:
%dpointer_p:
%2dproduced:
%2d\n",(int)tid,produce_pointer-1,buffer[produce_pointer-1]);
fprintf(fd,"producer:
%dpointer_p:
%2dproduced:
%2d\n",(int)tid,produce_pointer-1,buffer[produce_pointer-1]);
}
showbuf();
sem_post(&buffer_mutex);
sem_post(&consumer_semaphore);/*通知消费者缓冲区不是空的*/
srand((int)time(NULL)*(int)tid);
sleep(rand()%5+1);/*等待几秒钟,然后继续生产*/
}
return((void*)0);
}
void*consumer_thread(void*tid){
/*可以被其他线程使用*/
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
while
(1){
sem_wait(&consumer_semaphore);
srand((int)time(NULL)*(int)tid);
sleep(rand()%2+1);/*一个或两个来消费*/
sem_wait(&buffer_mutex);
printf("consumer:
%dpointer_c:
%2dconsumed:
%2d\n",(int)tid,consume_pointer,buffer[consume_pointer]);
fprintf(fd,"consumer:
%dpointer_c:
%2dconsumed:
%2d\n",(int)tid,consume_pointer,buffer[consume_pointer]);
buffer[consume_pointer]=0;
consume_pointer=(consume_pointer+1)%20;
showbuf();
sem_post(&buffer_mutex);
sem_post(&producer_semaphore);
srand((int)time(NULL)*(int)tid);
sleep(rand()%5+1);/*等待几秒钟,然后继续消费*/
}
return((void*)0);
}
/*查看缓冲区内容*/
voidshowbuf(){
inti;
printf("buffer:
");
fprintf(fd,"buffer:
");
for(i=0;iprintf("%2d",buffer[i]);
fprintf(fd,"%2d",buffer[i]);
}
printf("\n\n");
fprintf(fd,"\n\n");
}
5.运行结果与运行情况
程序运行结果如下:
producer:
1pointer_p:
0produced:
20
buffer:
200000000000000000000
producer:
3pointer_p:
1produced:
13
buffer:
2013000000000000000000
producer:
2pointer_p:
2produced:
6
buffer:
2013600000000000000000
producer:
4pointer_p:
3produced:
14
buffer:
20136140000000000000000
producer:
5pointer_p:
4produced:
20
buffer:
201361420000000000000000
consumer:
2pointer_c:
0consumed:
20
buffer:
01361420000000000000000
producer:
1pointer_p:
5produced:
20
buffer:
013614202000000000000000
consumer:
1pointer_c:
1consumed:
13
buffer:
00614202000000000000000
consumer:
3pointer_c:
2consumed:
6
buffer:
00014202000000000000000
consumer:
4pointer_c:
3consumed:
14
buffer:
0000202000000000000000
consumer:
5pointer_c:
4consumed:
20
buffer:
000002000000000000000
producer:
3pointer_p:
6produced:
1
buffer:
000002010000000000000
producer:
2pointer_p:
7produced:
14
buffer:
0000020114000000000000
consumer:
3pointer_c:
5consumed:
20
buffer:
000000114000000000000
producer:
4pointer_p:
8produced:
6
buffer:
000000114600000000000
consumer:
5pointer_c:
6consumed:
1
buffer:
000000014600000000000
producer:
5pointer_p:
9produced:
8
buffer:
000000014680000000000
consumer:
2pointer_c:
7consumed:
14
buffer:
00000000680000000000
consumer:
5pointer_c:
8consumed:
6
buffer:
00000000080000000000
producer:
1pointer_p:
10produced:
18
buffer:
000000000818000000000
consumer:
1pointer_c:
9consumed:
8
buffer:
000000000018000000000
producer:
2pointer_p:
11produced:
10
buffer:
0000000000181000000000
producer:
4pointer_p:
12produced:
10
buffer:
00000000001810100000000
consumer:
4pointer_c:
10consumed:
18
buffer:
0000000000010100000000
producer:
3pointer_p:
13produced:
3
buffer:
0000000000010103000000
consumer:
3pointer_c:
11consumed:
10
buffer:
000000000000103000000
consumer:
2pointer_c:
12consumed:
10
buffer:
00000000000003000000
producer:
1pointer_p:
14produced:
6
buffer:
00000000000003600000
consumer:
1pointer_c:
13consumed:
3
buffer:
00000000000000600000
producer:
2pointer_p:
15produced:
18
buffer:
000000000000006180000
consumer:
5pointer_c:
14consumed:
6
buffer:
000000000000000180000
producer:
1pointer_p:
16produced:
6
buffer:
000000000000000186000
producer:
3pointer_p:
17produced:
19
buffer:
0000000000000001861900
consumer:
1pointer_c:
15consumed:
18
buffer:
000000000000000061900
producer:
5pointer_p:
18produced:
7
buffer:
000000000000000061970
consumer:
3pointer_c:
16consumed:
6
buffer:
000000000000000001970
producer:
4pointer_p:
19produced:
14
buffer:
0000000000000000019714
consumer:
5pointer_c:
17consumed:
19
buffer:
000000000000000000714
consumer:
4pointer_c:
18consumed:
7
buffer:
000000000000000000014
producer:
1pointer_p:
0produced:
4
buffer:
400000000000000000014
consumer:
2pointer_c:
19consumed:
14
buffer:
40000000000000000000
consumer:
1pointer_c:
0consumed:
4
buffer:
00000000000000000000
producer:
2pointer_p:
1produced:
15
buffer:
015000000000000000000
producer:
3pointer_p:
2produced:
13
buffer:
0151300000000000000000
producer:
2pointer_p:
3produced:
3
buffer:
0151330000000000000000
说明:
“producer:
2”是指自定义标号为2的producer,“pointer_p