Chinaunix首页 | 论坛 | 博客
  • 博客访问: 444933
  • 博文数量: 60
  • 博客积分: 1039
  • 博客等级: 准尉
  • 技术积分: 939
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-01 09:24
个人简介

你是我的我是大家的!

文章分类
文章存档

2013年(1)

2012年(59)

分类: LINUX

2012-10-31 18:41:23

/**********************************************************************************************************************************************

*同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空 缓冲区中供消费者线程消费。消费者线程从缓冲区中获得
*物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费 者线程释放出一个空缓冲区。当消费
*者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来
*
*执行命令:
*#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;
 }

 
阅读(5542) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~