zoukankan      html  css  js  c++  java
  • Operating System Concepts 项目:生产者-消费者问题 线程

     一. 实验目的

          实现一个c程序,该程序能模拟解决有限缓冲问题,其中消费者和生产者产生和消耗随机数

    二.实验内容

    1. 缓冲区

    元数据类型为buffer_item,大小为1000的数组,按环形队列处理

    1. 生产者和消费者线程

    生产者不断执行如下两个操作:消费一个随机数,生产两个随机数

    消费者不断执行如下两个操作:生产一个随机数,消费两个随机数

    3.Pthead线程创建

    使用pthread_create创建5个生产者线程,5个消费者线程,主程序等待所有线程退出

    三. 实验环境

          Ubuntu Gnome 14.04

           MinGW 4.8.1

           Codeblocks 13.12

    四.实验结果

    基本采用semaphore实现了题目要求,其中

    psem用于标示是否可生产(数量是否超过缓冲区大小),初始量为1000,每次消费+1,

    csem用于标示是否可消费,初始量为0,每次生产+1,

    sem用于标示是否可以修改缓冲区

    但是以下情况会发生,导致程序死锁:

    例如:5个消费者生产5个随机数,随后消耗这5个随机数,则生产者无法先消耗随机数再生产

    五.附录

    调试心得:
    1.  有限缓冲问题确实可能死锁
    2.  Pthread_create(tid,attr,func_name,arg)最后一个参数表示唯一传给线程的参数
    3.  Void *func_name(void *arg)return需要用pthread_exit(),这个函数的作用是,终止调用它的线程并返回一个指向某个对象的指针,但是直接调用exit(0)会使整个进程退出. 如果主线程调用了pthread_exit,那么它退出了,子线程也不会退出。如果是return 0则会直接退出.
    4.  使用函数pthread_exit退出线程,这是线程的主动行为;由于一个进程中的多个线程是共享数据段的,因此通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放,但是可以用pthread_join()函数来同步并释放资源。在Linux中,默认情况下是在一个线程被创建后,必须使用此函数对创建的线程进行资源回收,但是可以设置Threads attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源
    5.  在线程函数在编译时,需要连接库函数, -lpthread
     
    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    typedef int item;
    const int bsize = 1000;
    const int pnum = 5;
    const int cnum = 10;
    const int looptimes = 10000;
    sem_t sem,psem,csem;
    
    
    struct que{
        item a[bsize];
        int head,tail,n;
        que(){
            memset(a,0,sizeof(a));
            head=tail=n=0;
        }
    }q;
    
    void p(char * str,int num){
        while(num--){
            sem_wait(&psem);
            sem_wait(&sem);
            q.a[q.head]=rand()%10;
            q.n++;
            printf("%s: produce a[%d]:%d, now there is %d numbers in queue
    ",str,q.head,q.a[q.head],q.n);
            q.head=(q.head+1)%bsize;
            sem_post(&csem);
            sem_post(&sem);
        }
    }
    
    void c(char *str,int num){
        while(num--){
            sem_wait(&csem);
            sem_wait(&sem);
            q.n--;
            printf("%s: consume a[%d]:%d, now there is %d numbers in queue
    ",str,q.tail,q.a[q.tail],q.n);
            q.tail=(q.tail+1)%bsize;
            sem_post(&psem);
            sem_post(&sem);
        }
    }
    
    void * producer(void * arg){
        for(int i=0;i<looptimes;i++){
            c((char*)arg,1);
            p((char*)arg,2);
        }
        pthread_exit(0);
    }
    void * consumer(void * arg){
        for(int i=0;i<looptimes;i++){
            p((char*)arg,1);
            c((char*)arg,2);
        }
        pthread_exit(0);
    }
    int main(){
        sem_init(&sem,0,1);
        sem_init(&psem,0,1000);
        sem_init(&csem,0,0);
        char pname[5][3]={"p1","p2","p3","p4","p5"};
        char cname[5][3]={"c1","c2","c3","c4","c5"};
        pthread_t ptid[5],ctid[5];
        pthread_attr_t pattr[5],cattr[5];
        for(int i=0;i<5;i++){
            pthread_attr_init(pattr+i);
            pthread_create(ptid+i,pattr+i,producer,pname[i]);
            pthread_attr_init(cattr+i);
            pthread_create(ctid+i,cattr+i,consumer,cname[i]);
        }
        for(int i=0;i<5;i++){
            pthread_join(ptid[i],NULL);
            pthread_join(ctid[i],NULL);
        }
        puts("end");
        return 0;
    }
  • 相关阅读:
    【Python 开发】第三篇:python 实用小工具
    【Python 开发】第二篇 :Python安装
    【Linux 运维】 安装PHP工具Composer
    【shell 每日一练6】初始化安装Mysql并修改密码
    【zabbix 监控】第三章 创建主机组和主机
    【Docker】第一篇 Docker的初始化安装部署
    【shell 练习5】编写简单的多级菜单
    【zabbix 监控】第二章 安装测试被监控主机
    【zabbix 监控】第一章 zabbix的安装配置
    1数组和字符串题解
  • 原文地址:https://www.cnblogs.com/xuesu/p/4474496.html
Copyright © 2011-2022 走看看