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;
}
原文地址:https://www.cnblogs.com/xuesu/p/4474496.html