用多线程同步方法解决生产者消费者问题.docx
- 文档编号:8701888
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:14
- 大小:41.94KB
用多线程同步方法解决生产者消费者问题.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;i pthread_cancel(threads_p[i]); for(i=0;i pthread_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;i buffer[i]=0;/*引发缓冲*/ /*创建线程*/ for(i=0;i pthread_create(&threads_p[i],NULL,(void*)producer_thread,(void*)(i+1)); for(i=0;i pthread_create(&threads_c[i],NULL,(void*)consumer_thread,(void*)(i+1)); alarm(RUN_TIME); /*等待线程退出*/ for(i=0;i pthread_join(threads_p[i],NULL); for(i=0;i pthread_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;i printf("%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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多线程 同步 方法 解决 生产者 消费者 问题