最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

用多线程同步方法解决生产者-消费者问题

来源:动视网 责编:小OO 时间:2025-10-01 10:04:06
文档

用多线程同步方法解决生产者-消费者问题

武汉理工大学华夏学院课程设计报告书课程名称:操作系统原理题目:用多线程同步方法解决生产者-消费者问题系名:信息工程系专业班级:姓名:学号:指导教师:年月日课程设计任务书学生姓名:专业班级:指导教师:工作单位:设计题目:用多线程同步方法解决生产者-消费者问题初始条件:Linux操作系统,GCC编译环境要求完成的主要任务:主要任务:通过研究Linux的线程机制和信号量实现生产者消费者问题的并发控制。有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1~20这20个整型数。(1)每个生产者和消
推荐度:
导读武汉理工大学华夏学院课程设计报告书课程名称:操作系统原理题目:用多线程同步方法解决生产者-消费者问题系名:信息工程系专业班级:姓名:学号:指导教师:年月日课程设计任务书学生姓名:专业班级:指导教师:工作单位:设计题目:用多线程同步方法解决生产者-消费者问题初始条件:Linux操作系统,GCC编译环境要求完成的主要任务:主要任务:通过研究Linux的线程机制和信号量实现生产者消费者问题的并发控制。有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1~20这20个整型数。(1)每个生产者和消
武汉理工大学华夏学院

课程设计报告书

课程名称: 操作系统原理     

题    目:用多线程同步方法解决生产者-消费者问题

      系    名:        信息工程系         

专业班级:           

姓    名:                                              

学    号:              

指导教师:                   

  年  月  日

课程设计任务书

学生姓名:          专业班级:      

指导教师:          工作单位:       

设计题目:用多线程同步方法解决生产者-消费者问题

初始条件:

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-Consumer Problem)的并发控制。

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.详细算法描述

共享数据:

Semaphore buffer_mutex=1;

Semaphore producer_semaphore=MAX_BUFFER;

Semaphore consumer_semaphore=0;

int buffer[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

#define NUM_THREADS_P 5  /*定义数据为生产者*/

#define NUM_THREADS_C 5  /*定义数据为消费者*/

#define MAX_BUFFER 20    /*定义数据为缓存区*/

#define RUN_TIME 20         /*定义运行时间*/

int buffer[MAX_BUFFER];  

int produce_pointer=0,consume_pointer=0;

sem_t producer_semaphore,consumer_semaphore,buffer_mutex;

pthread_t threads_p[NUM_THREADS_P]; /*声明生产者线程*/

pthread_t threads_c[NUM_THREADS_C]; /*声明消费者线程*/

FILE* fd; 

void *producer_thread(void *tid);

void *consumer_thread(void *tid);

void showbuf();

void handler(){

    int i;

for(i=0;i        pthread_cancel(threads_p[i]);

for(i=0;i        pthread_cancel(threads_c[i]);

}

int main(){

    int i;

    signal(SIGALRM,handler);

    fd=fopen("output.txt打开一个文件用来保存结果*/

    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);

    return 0;

}

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:%d   pointer_p:%2d   produced:%2d\\n",(int)tid,19,buffer[19]);

            fprintf(fd,"producer:%d   pointer_p:%2d   produced:%2d\\n",(int)tid,19,buffer[19]);

        }

        else{

            printf("producer:%d   pointer_p:%2d   produced:%2d\\n",(int)tid,produce_pointer-1,buffer[produce_pointer-1]);

            fprintf(fd,"producer:%d   pointer_p:%2d   produced:%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:%d   pointer_c:%2d   consumed:%2d\\n",(int)tid,consume_pointer,buffer[consume_pointer]);

        fprintf(fd,"consumer:%d   pointer_c:%2d   consumed:%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);

}

/*查看缓冲区内容*/

void showbuf(){

    int i;

    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:1   pointer_p: 0   produced:20

buffer:20  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:3   pointer_p: 1   produced:13

buffer:20 13  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:2   pointer_p: 2   produced: 6

buffer:20 13  6  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:4   pointer_p: 3   produced:14

buffer:20 13  6 14  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:5   pointer_p: 4   produced:20

buffer:20 13  6 14 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:2   pointer_c: 0   consumed:20

buffer: 0 13  6 14 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:1   pointer_p: 5   produced:20

buffer: 0 13  6 14 20 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:1   pointer_c: 1   consumed:13

buffer: 0  0  6 14 20 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:3   pointer_c: 2   consumed: 6

buffer: 0  0  0 14 20 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:4   pointer_c: 3   consumed:14

buffer: 0  0  0  0 20 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:5   pointer_c: 4   consumed:20

buffer: 0  0  0  0  0 20  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:3   pointer_p: 6   produced: 1

buffer: 0  0  0  0  0 20  1  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:2   pointer_p: 7   produced:14

buffer: 0  0  0  0  0 20  1 14  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:3   pointer_c: 5   consumed:20

buffer: 0  0  0  0  0  0  1 14  0  0  0  0  0  0  0  0  0  0  0  0 

producer:4   pointer_p: 8   produced: 6

buffer: 0  0  0  0  0  0  1 14  6  0  0  0  0  0  0  0  0  0  0  0 

consumer:5   pointer_c: 6   consumed: 1

buffer: 0  0  0  0  0  0  0 14  6  0  0  0  0  0  0  0  0  0  0  0 

producer:5   pointer_p: 9   produced: 8

buffer: 0  0  0  0  0  0  0 14  6  8  0  0  0  0  0  0  0  0  0  0 

consumer:2   pointer_c: 7   consumed:14

buffer: 0  0  0  0  0  0  0  0  6  8  0  0  0  0  0  0  0  0  0  0 

consumer:5   pointer_c: 8   consumed: 6

buffer: 0  0  0  0  0  0  0  0  0  8  0  0  0  0  0  0  0  0  0  0 

producer:1   pointer_p:10   produced:18

buffer: 0  0  0  0  0  0  0  0  0  8 18  0  0  0  0  0  0  0  0  0 

consumer:1   pointer_c: 9   consumed: 8

buffer: 0  0  0  0  0  0  0  0  0  0 18  0  0  0  0  0  0  0  0  0 

producer:2   pointer_p:11   produced:10

buffer: 0  0  0  0  0  0  0  0  0  0 18 10  0  0  0  0  0  0  0  0 

producer:4   pointer_p:12   produced:10

buffer: 0  0  0  0  0  0  0  0  0  0 18 10 10  0  0  0  0  0  0  0 

consumer:4   pointer_c:10   consumed:18

buffer: 0  0  0  0  0  0  0  0  0  0  0 10 10  0  0  0  0  0  0  0 

producer:3   pointer_p:13   produced: 3

buffer: 0  0  0  0  0  0  0  0  0  0  0 10 10  3  0  0  0  0  0  0 

consumer:3   pointer_c:11   consumed:10

buffer: 0  0  0  0  0  0  0  0  0  0  0  0 10  3  0  0  0  0  0  0 

consumer:2   pointer_c:12   consumed:10

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  3  0  0  0  0  0  0 

producer:1   pointer_p:14   produced: 6

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  3  6  0  0  0  0  0 

consumer:1   pointer_c:13   consumed: 3

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  6  0  0  0  0  0 

producer:2   pointer_p:15   produced:18

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  6 18  0  0  0  0 

consumer:5   pointer_c:14   consumed: 6

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 18  0  0  0  0 

producer:1   pointer_p:16   produced: 6

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 18  6  0  0  0 

producer:3   pointer_p:17   produced:19

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 18  6 19  0  0 

consumer:1   pointer_c:15   consumed:18

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  6 19  0  0 

producer:5   pointer_p:18   produced: 7

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  6 19  7  0 

consumer:3   pointer_c:16   consumed: 6

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 19  7  0 

producer:4   pointer_p:19   produced:14

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 19  7 14 

consumer:5   pointer_c:17   consumed:19

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  7 14 

consumer:4   pointer_c:18   consumed: 7

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 14 

producer:1   pointer_p: 0   produced: 4

buffer: 4  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 14 

consumer:2   pointer_c:19   consumed:14

buffer: 4  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

consumer:1   pointer_c: 0   consumed: 4

buffer: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:2   pointer_p: 1   produced:15

buffer: 0 15  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:3   pointer_p: 2   produced:13

buffer: 0 15 13  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

producer:2   pointer_p: 3   produced: 3

buffer: 0 15 13  3  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 

说明: 

“producer:2”是指自定义标号为2的producer,“pointer_p:3”是指该producer的指针,“produced:3”是指该producer在buffer[3]里写入3,“buffer: 0 15 13  3  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 ”是指该producer进行写操作后存储区的内容。

6.调试过程

通过这次课程设计,不但加深了对操作系统这们课程的认识,而且还了解了操作系统中使用信号量解决生产者—消费者问题算法的实现。比如:用信号量解决生产者—消费者问题时,可以通过一个有界缓冲区(用数组来实现,类似循环队列)把生产者和消费者联系起来。假定生产者和消费者的优先级是相同的,只要缓冲区未满,生产者就可以生产产品并将产品送入缓冲区。类似地,只要缓冲区未空,消费者就可以从缓冲区中去走产品并消费它。为了解决生产者/消费者问题,应该设置两个资源信号量,其中一个表示空缓冲区的数目,用producer_semaphore表示,其初始值为有界缓冲区的大小SIZE_OF_BUFFER;另一个表示缓冲区中产品的数目,用consumer_semaphore表示,其初始值为0。另外,由于有界缓冲区是一个临界资源,必须互斥使用,所以还需要再设置一个互斥信号量buffer_mutex,起初值为1。在生产者/消费者问题中,信号量实现两种功能。首先,它是生产产品和消费产品的计数器,计数器的初始值是可利用的资源数 目(有界缓冲区的长度)。其次,它是确保产品的生产者和消费者之间动作同步的同步器。生产者要生产一个产品时,首先对资源信号量producer_semaphore和互斥信号量buffer_mutex进行wait操作,申请资源。如果可以通过的话,就生产一个产品,并把产品送入缓冲区。然后对互斥信号量buffer_mutex和资源信号量consumer_semaphore进行signal操作,释放资源。消费者要消费一个产品时,首先对资源信号量consumer_semaphore和互斥信号量buffer_mutex进行wait操作,申请资源。如果可以通过的话,就从缓冲区取出一个产品 并消费掉。然后对互斥信号量buffer_mutex和资源信号量producer_semaphore进行signal操作,释放资源。

7.总结

通过本次课程设计,我巩固了使用多线程编程的方法,和使用信号量同步进/线程的技巧。本次课程设计的程序的运行结果跟预期的一致,说明该程序能顺利解决生产者消费者问题,实现了本次课程设计的目的。

另外,使我体会最深的是:任何一门知识的掌握,仅靠学习理论知识是远远不够的,要与实际动手操 作相结合才能达到功效。短短的课程设计就要结束了,不但对专业知识有了更深的理解,更使自己认识到 实践的重要性,理论、实践相结合才能达到很好的学习效果,特别是程序语言的学习。

设计过程中质疑(或答辩)记载:

{设计报告书中的最后一页}

指导教师评语:

                                           

签名:

  

                                             年       月       日

 

文档

用多线程同步方法解决生产者-消费者问题

武汉理工大学华夏学院课程设计报告书课程名称:操作系统原理题目:用多线程同步方法解决生产者-消费者问题系名:信息工程系专业班级:姓名:学号:指导教师:年月日课程设计任务书学生姓名:专业班级:指导教师:工作单位:设计题目:用多线程同步方法解决生产者-消费者问题初始条件:Linux操作系统,GCC编译环境要求完成的主要任务:主要任务:通过研究Linux的线程机制和信号量实现生产者消费者问题的并发控制。有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1~20这20个整型数。(1)每个生产者和消
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top