Linux下生产者消费者问题详细分析(操作系统期中考试论文---并发程序的同步和互斥)

转运四方海淘网

这是操作系统期中考试时我写的小论文,想要文档及代码的点击下载

要求如下:

本篇为了简洁,只贴有用的信息。

执行逻辑说明:

         程序启动后首先初始化信号量集和循环缓冲队列。然后按照提示信息输入生产者数量和消费者数量。根据生产者和消费者数量创建相应的生产者线程和消费者线程。生产者线程执行生产者函数,向缓冲区放一个值,然后write指针加1。消费者执行消费者函数,从缓冲区读一个值,然后read指针加1。

源码如下:

/* pc.c:Producer and Consumer Problem
   *author : houjialin
   *To compile: g++ pc.c -o pc -l pthread
   */
#include<stdio.h>
#include<stdlib.h>//exit
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<pthread.h>
#include <unistd.h>//sleep
#include<signal.h>
#define Maxbuf 10  
//定义循环缓冲队列及对其的一组操作
struct Circlebuf//循环缓冲队列结构
{
    int read;//读指针
     int write;//写指针
     int buf[Maxbuf];//缓冲区
} circlebuf;
void writeCirclebuf(Circlebuf *circlebuf,int *value)//向缓冲区中写一个值
{
        circlebuf->buf[circlebuf->write]=(*value);  
        circlebuf->write=(circlebuf->write+1)%Maxbuf;//写过后指针+1
       
}
int  readCirclebuf(Circlebuf *circlebuf)//从当前指针读一个值,返回value
{
    int value=0;
    value=circlebuf->buf[circlebuf->read];
    circlebuf->buf[circlebuf->read]=0; //读过后置0
    circlebuf->read=(circlebuf->read+1)%Maxbuf;//读过后read+1
    return value;
}
void OutCirclebuf(Circlebuf *circlebuf)
{
     printf("Circlebuf value:");
     for(int i=0;i<Maxbuf;i++)
     {
       printf("%d  ", circlebuf->buf[i]);
     }
     printf("\n");
}
//定义信号量及对其的操作
#define SEM_Key 4001 //信号量Key值 
struct sembuf semaphore;//定义一个信号量
int semid;//信号量ID
bool initSembuf()//创建信号量集,并初始化
{
    int sem=0;
    if((semid=semget(SEM_Key,3,IPC_CREAT|0666))>=0)
      {
       sem=1;
       semctl(semid,0,SETVAL,sem);//第0个信号量,初值为1,缓冲区互斥使用(mutex)
       sem=10;
       semctl(semid,1,SETVAL,sem);//第1个信号量,初值为10,当前空缓冲区数(empty)
       sem=0;
       semctl(semid,2,SETVAL,sem);//第2个信号量,初值为0,当前满缓冲区数(full)
       return true;
      }
    else 
       return false;
}
//对信号量的PV操作
void Pmutex()
{
   semaphore.sem_num=0;  
   semaphore.sem_op=-1;  
   semaphore.sem_flg=SEM_UNDO;
   semop(semid,&semaphore,1);
}
void Vmutex()
{
  semaphore.sem_num=0;  
  semaphore.sem_op=1;  
  semaphore.sem_flg=SEM_UNDO;
  semop(semid,&semaphore,1);
}
void Pempty()
{
   semaphore.sem_num=1;  
   semaphore.sem_op=-1;  
   semaphore.sem_flg=SEM_UNDO;
   semop(semid,&semaphore,1);
}
void Vempty()
{
   semaphore.sem_num=1;  
   semaphore.sem_op=1;  
   semaphore.sem_flg=SEM_UNDO;
   semop(semid,&semaphore,1);
}
void Pfull()
{
   semaphore.sem_num=2;  
   semaphore.sem_op=-1;  
   semaphore.sem_flg=SEM_UNDO;
   semop(semid,&semaphore,1);
}
void Vfull()
{
   semaphore.sem_num=2;  
   semaphore.sem_op=1;  
   semaphore.sem_flg=SEM_UNDO;
   semop(semid,&semaphore,1);
}
void sigend(int sig)  
{  
    semctl(semid, IPC_RMID, 0);  
    exit(0);  
}  
void * productThread(void *i)//生产者线程
{
  int *n=(int *)i;
  while(true)
  {
     Pempty();//①
     Pmutex();//②
     writeCirclebuf(&circlebuf,n);
     printf("Producer %d succeeded put a value=%d into the circlebuf.\n",*n,*n);
     OutCirclebuf(&circlebuf);
     Vmutex();//③
     Vfull();//④
  }
}
void * consumerThread(void *i)//消费者
{
  int *n=(int *)i;
  int value=0;//消费品存放处
  while(true)
  {
       Pfull();//⑤
       Pmutex();//⑥
       value=readCirclebuf(&circlebuf);
       printf("The consumer %d succeful consume .The value is %d \n",*n,value);
       Vmutex();//⑦
       Vempty();//⑧
  }
}
int main()
{
   While(! initSembuf());//初始化信号量集
   signal(SIGINT, sigend); 
   signal(SIGTERM, sigend); 
   int ConsNum=0,ProdNum=0,ret;//初始化生产者消费者数量
   pthread_t  cpid,ppid;//线程ID
   //初始化循环缓冲队列
   circlebuf.read=circlebuf.write=0;
   for(int i=0;i<Maxbuf;i++)
    {
      circlebuf.buf[i]=0;
    }
   printf("Please input the number of producter :");
   scanf("%d",&ProdNum);
   int *pro=new int[ProdNum];
   printf("Please input the number of consumer :");
   scanf("%d",&ConsNum);
   int *con=new int[ConsNum]; 
   for(int i=1;i<=ProdNum;i++)//启动生产者
     {
        ppid=i+100;//为了和消费者线程ID区别,每个线程号都加100
        pro[i-1]=i;
        ret=pthread_create(&ppid,NULL,productThread,(void *)&pro[i-1]);//
        if(ret!=0)
        {
         printf("Create thread error");
         exit(1);
        }
     }
   for(int i=1;i<=ConsNum;i++)//启动消费者
     {
       cpid=i;
       con[i-1]=i;
       ret=pthread_create(&cpid,NULL,consumerThread,(void *)&con[i-1]);
       if(ret!=0)
       {
         printf("Create thread error");
         exit(1);
       }
     }
   sleep(100000);//不让main线程停止
}

编程平台说明:

操作系统:Ubuntu11.04

编译器:  g++

同步机制:采用Linux下的信号量机制实现并发进程间的同步和互斥。源程序建立的信号量集中有三个信号量。第一信号量初值为1,缓冲区互斥时使用。第二个初值为10,相当于当前可用空缓冲区数量。第三个初值为0,表示当前已放入产品的缓冲区数量。

静态条件说明和执行结果分析:

(由于格式换着太麻烦了,这里直接上图片了。)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值