发新话题
打印

生产者消费者

生产者消费者

/*两个线程共享一个公共的、固定大小的缓冲区。
其中的一个线程,即生产者,向缓冲区放入信息,
另外一个线程,即消费者,从缓冲区中取走信息(
该问题也可以一般化为 m 个生产者和 n个消费者)。
当生产者向缓冲区放入信息时,如果缓冲区是满的,则生产者进入休眠,
而当消费者从缓冲区中拿走信息后,可唤醒生产者;
当消费者从缓冲区中取信息时,如果缓冲区为空,则消费者进入休眠,
而当生产者向缓冲区写入信息后,可唤醒消费者。*/
#include <stdio.h>
#include <pthread.h>
#define BUFFER_SIZE 16
#define N 200
/* Circular buffer of integers. */
struct prodcons {
  int data[BUFFER_SIZE];      /*  实际数据 */
  int readpos;                /*读取位置*/   
  int writepos;               /* 写入的位置 */
  int read_elmts;             /* 可读取的元素个数 */
  int write_elmts;            /* 可写入的空位个数 */
}buffer;
  pthread_mutex_t mutex;//生产者和消费者的互斥量
  pthread_cond_t condw;/*用于写的条件变量*/
  pthread_cond_t condr;/*用于读的条件变量*/
  
//生产者函数
void * producer()
{
  int i;
  
  for(i = 0;i<N+1;i++)
  {
   pthread_cleanup_push((void*)pthread_mutex_unlock,&mutex);//线程清理
   pthread_mutex_lock(&mutex);//加锁
   if(buffer.write_elmts == 0)  //缓冲区已满
   pthread_cond_wait(&condw,&mutex);//等待条件变量
   //访问临界数据区
   if(buffer.writepos == BUFFER_SIZE)
   buffer.writepos = 0;    //返回到起始地址
   buffer.data[buffer.writepos] = i;
   buffer.writepos++;
   printf("生产者正在生产商品%d\n",i);
   buffer.read_elmts++;
   buffer.write_elmts--;
   //访问结束
   if(buffer.read_elmts!=0)  //当前读出缓冲区中有数据
    pthread_cond_signal(&condr);//激活条件变量
   pthread_mutex_unlock(&mutex);//解锁
   pthread_cleanup_pop(0);//线程清理
   }
   
   return NULL;
}
void * consumer()
{
  while (1)
  {
   pthread_cleanup_push((void*)pthread_mutex_unlock,(void*)&mutex);
   pthread_mutex_lock(&mutex);//加锁;
   if(buffer.read_elmts == 0)  //缓冲区已空,无可读元素
   pthread_cond_wait(&condr,&mutex);//等待条件变量
   if(buffer.data[buffer.readpos] == N)
   exit(0);
   printf("消费者正在消费商品%d\n",buffer.data[buffer.readpos]);
   buffer.readpos++;
   if(buffer.readpos == BUFFER_SIZE)  //读到最后一个位置时返回第一个位置
   buffer.readpos = 0;
   buffer.write_elmts++;
   buffer.read_elmts--;
   if(buffer.write_elmts!= 0)
   pthread_cond_signal(&condw);//激活条件变量
   pthread_mutex_unlock(&mutex);//解锁
   pthread_cleanup_pop(0);
  
   }

}

int main(void)
{
  pthread_t th_a, th_b;
  int retval[1][1];
/*retval = (int*)malloc(16);
  for(i =0 ;i<16;i++)
(*retval) = malloc(sizeof(int));*/
  memset(&buffer,0,sizeof(struct prodcons )); //清空缓冲区
  buffer.write_elmts = BUFFER_SIZE;
  pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//初始化互斥锁
  pthread_cond_t condr=PTHREAD_COND_INITIALIZER;//初始化读条件变量
  pthread_cond_t condw=PTHREAD_COND_INITIALIZER;//初始化写条件变量
  /* 建立生产者和消费者线程。*/
  pthread_create(&th_a,NULL,producer,(void *)NULL);
  pthread_create(&th_b,NULL,consumer,(void *)NULL);
  /* 等待生产者和消费者结束。 */
  pthread_join(th_a, (void**)retval);
  pthread_join(th_b, (void**)retval);
  //销毁互斥锁和条件变量
  pthread_mutex_destroy(&mutex);
  pthread_mutex_destroy(&condr);
  pthread_mutex_destroy(&condw);
  
  return 0;
}

TOP

Q1:线程创建时,参数void *(*start_routine) (void*)的含义。要求弄清楚函数指针的定义
Q2:线程清理处理程序的执行过程,讲解pushpop.c要求能说明pthread_cancel_pop(int execute);中execute为0和非0的作用
Q3:讲解unlock.c和lock.c时要求回答程序的输出,并与实际输出相比较,然后分析原因

为0,失效,为1,起作用。相当于堆栈,反序出栈

Unlock.输出次序乱,因为没有加互斥锁。哪个线程获得CPU,哪个就运行
Lock.c按次序先输出主线程,然后输出次线程

TOP

好了把它删了.................

TOP

题目二:利用互斥锁和条件变量编程解决生产者-消费者问题。

TOP

发新话题