生产者消费者
/*两个线程共享一个公共的、固定大小的缓冲区。
其中的一个线程,即生产者,向缓冲区放入信息,
另外一个线程,即消费者,从缓冲区中取走信息(
该问题也可以一般化为 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;
}