/**********************************************************************************************************************************************
*同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空 缓冲区中供消费者线程消费。消费者线程从缓冲区中获得
*物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费 者线程释放出一个空缓冲区。当消费
*者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来
*
*执行命令:
*#gcc pthread.c -o pth -lpthread
*#./pth
*
***************************************************************************************************************************************************/
/************************************************
*
* The classic producer-consumer example.
* Illustrates mutexes and conditions.
* by Zou jian guo
* 2003-12-22
*
*************************************************/
#include
#include
#include
#include "pthread.h"
#define BUFFER_SIZE 16
/* 循环缓冲区中的整数 */
struct prodcons {
int buffer[BUFFER_SIZE]; /* 实际数据 */
pthread_mutex_t lock; /* 互斥确保独家访问缓冲区 */
int readpos, writepos; /* 职位的阅读和写作 */
pthread_cond_t notempty; /* 发出信号时,缓冲区不为空 */
pthread_cond_t notfull; /* 发出信号时,缓冲区是不完整的 */
};
/*--------------------------------------------------------*/
/* 初始化一个缓冲区 */
void init(struct prodcons *b)
{
pthread_mutex_init(&b->lock, NULL); //互斥量初始化,即初始化互斥锁
pthread_cond_init(&b->notempty, NULL); //设置条件变量notempty是进程内可用还是进程间可用默认值是PTHREAD_PROCESS_PRIVATE,即此条件变量被同一进程内的各个线程使用
pthread_cond_init(&b->notfull, NULL); //设置条件变量notfull是进程内可用还是进程间可用默认值是PTHREAD_PROCESS_PRIVATE,即此条件变量被同一进程内的各个线程使用
b->readpos = 0;
b->writepos = 0;
}
/*--------------------------------------------------------*/
/* 存储在缓冲区中的整数 */
void put(struct prodcons *b, int data)
{
pthread_mutex_lock(&b->lock); //锁定互斥量,加锁(阻塞)
/* 等待缓冲区不充分 */
while ((b->writepos + 1) % BUFFER_SIZE == b->readpos)
{ //判断等待缓存区不满.
printf("wait for not full\n");
pthread_cond_wait(&b->notfull, &b->lock); //使此线程函数阻塞在条件变量notfull上
}
/* 写数据和预先写指针 */
b->buffer[b->writepos] = data; //如果等待队列不满,将数据data写入缓存区buffer中相应的能写的位置
b->writepos++; //将写位置向后偏移一个位置
if (b->writepos >= BUFFER_SIZE)
b->writepos = 0; //如果写位置超出了缓存区的大小,则将写位置清零从头写
/* 信号的缓冲区,现在没空 */
pthread_cond_signal(&b->notempty); //释放被阻塞在条件变量notempty上的一个线程
pthread_mutex_unlock(&b->lock); //解锁互斥量,解锁
}
/*--------------------------------------------------------*/
/* 读取和删除一个整数从缓冲区 */
int get(struct prodcons *b)
{
int data;
pthread_mutex_lock(&b->lock); //锁定互斥量,加锁(阻塞)
/* 等待,直到缓冲区不为空 */
while (b->writepos == b->readpos)
{ //判断写位置也能被读这缓存区有数据不为空
printf("wait for not empty\n");
pthread_cond_wait(&b->notempty, &b->lock); //使此线程函数阻塞在条件变量notempty上
}
/* 读取数据和读取指针 */
data = b->buffer[b->readpos]; //将缓存去可读的有效数据传给data
b->readpos++; //将要读数据的位置向下+1
if (b->readpos >= BUFFER_SIZE)
b->readpos = 0; //判断如果读位置超出啦缓存区,则从头读取
/* 信号的缓冲区,现在是不完整的 */
pthread_cond_signal(&b->notfull); //释放被阻塞在条件变量notfull上的一个线程
pthread_mutex_unlock(&b->lock); //解锁互斥量,解锁
return data;
}
/*--------------------------------------------------------*/
#define OVER (-1)
struct prodcons buffer;//定义生产者结构体类型变量为buffer的存储区的结构体
/*--------------------------------------------------------*/
void *producer(void *data)
{
int n;
for (n = 0; n < 1000; n++)
{
printf(" put-->%d\n", n);
put(&buffer, n); //将数据n写入缓存区buffer
}
put(&buffer, OVER); //将数据OVER写入缓存区buffer
printf("producer stopped!\n");
return NULL;
}
/*--------------------------------------------------------*/
void *consumer(void *data)
{
int d;
while (1)
{
d = get(&buffer); //将从buffer读取的数据方数d中
if (d == OVER)
break; //判断读取的字符是不是over,若是则停止消费
printf(" %d-->get\n", d);
}
printf("consumer stopped!\n");
return NULL;
}
/*--------------------------------------------------------*/
int main(void)
{
pthread_t th_a, th_b; //定义线程号
void *retval; //返回任意类型的指针
init(&buffer); //初始化缓存区
pthread_create(&th_a, NULL, producer, 0); //创建并跳转到参数为指向线程标识符的指针th_a线程函数producer
pthread_create(&th_b, NULL, consumer, 0); //创建并跳转到参数为指向线程标识符的指针th_b线程函数consumer
/* 等到生产者和消费者完成 */
pthread_join(th_a, &retval); //等待线程号为th_a线程函数结束,并将返回值保存入retval
pthread_join(th_b, &retval); //等待线程号为th_b线程函数结束,并将返回值保存入retval
return 0;
}
阅读(5602) | 评论(0) | 转发(0) |