Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4462887
  • 博文数量: 1148
  • 博客积分: 25453
  • 博客等级: 上将
  • 技术积分: 11949
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 21:14
文章分类

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: C/C++

2011-05-16 12:56:03

条件变量 函数:
  1. 初始化 :pthread_cond_init
  2. 阻塞等待: pthread_cond_wait
  3. 通知等待的第一个线程: pthread_cond_signal
  4. 指定时间内阻塞等待: pthread_cond_timewait
  5. 通知所有等待的线程: pthread_cond_broadcast
  6. 销毁: pthread_cond_destroy

分析 pthread_cond_wait 和 pthread_cond_signal  实现


    等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()的竞争条件(Race Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。 
  
  激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。


实例:生产者 消费者 问题

    整个存储空间为 2 ,在任意时刻,最多只能有2个产品存放在临时空间。如果已经有2个产品存放在临时空间,将阻塞生产线程。同理,如果临时空间没有产品,显示需要阻塞消费线程。
    实现 生产 和 消费 的线程的同步

  1. #include <stdio.h> //printf
  2. #include <pthread.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>

  6. #define BUFFER_SIZE 2

  7. struct product_cons
  8. {
  9.     int buffer[BUFFER_SIZE]; //生产产品值
  10.     pthread_mutex_t lock; //互斥锁 volatile int
  11.     int readpos, writepos;    //读写位置
  12.     pthread_cond_t notempty; //条件变量,非空
  13.     pthread_cond_t notfull; //非满
  14.     /* typedef struct{
  15.         int volatile value;
  16.             }pthread_cont_t;*/
  17. };

  18. void init(struct product_cons *p)
  19. {
  20.     pthread_mutex_init(&p->lock, NULL); //互斥锁
  21.     pthread_cond_init(&p->notempty, NULL);//条件变量
  22.     pthread_cond_init(&p->notfull, NULL); //条件变量
  23.     p->readpos = 0; //读写位置
  24.     p->writepos = 0;
  25. }

  26. //存储 一个数据 到 bufferr
  27. void put(struct product_cons *p, int data) //输入产品子函数
  28. {
  29.     pthread_mutex_lock(&p->lock); //上锁
  30.     
  31.     /*等待,直到 buffer 不为 满*/
  32.     while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满
  33.     {
  34.         printf("producer wait for not full\n");
  35.         pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待
  36.         //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号
  37.         //如果,消费者发送了 signal 信号,表示有了 空闲
  38.     }

  39.     p->buffer[p->writepos] = data; //写数据
  40.     p->writepos++;

  41.     if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回
  42.         p->writepos = 0;
  43.     
  44.     pthread_cond_signal(&p->notempty); //发送有数据信号
  45.     pthread_mutex_unlock(&p->lock); //解锁
  46.     
  47. }

  48. //读,移除 一个数据 从 buffer
  49. int get(struct product_cons *p)
  50. {
  51.     int data;
  52.     pthread_mutex_lock(&p->lock);

  53.     /*等待,直到不为空*/
  54.     while(p->writepos == p->readpos)
  55.     {
  56.         printf("consumer wait for not empty\n");
  57.         pthread_cond_wait(&p->notempty,&p->lock);
  58.     }

  59.     /*读 一个 数据*/
  60.     data = p->buffer[p->readpos];
  61.     
  62.     p->readpos++;
  63.     if(p->readpos >= BUFFER_SIZE) //如果读到 尾
  64.         p->readpos = 0;
  65.     pthread_cond_signal(&p->notfull);
  66.     pthread_mutex_unlock(&p->lock);
  67.     return data;    
  68. }

  69. #define OVER (-1)
  70. struct product_cons buffer;

  71. void *producer(void *data) //子线程 ,生产
  72. {
  73.     int n;
  74.     for(n = 1; n <=5; n++) //生产 前5 个产品
  75.     {
  76.         printf("producer sleep 1 second ...\n"); //每一秒 生产 一个
  77.         sleep(1);
  78.         printf("put the %d product\n",n);
  79.         put(&buffer,n);
  80.     }
  81.     for(n=6; n<10; n++)
  82.     {
  83.         printf("producer sleep 3 second...\n");
  84.         sleep(3);
  85.         printf("put the %d product",n);
  86.         put(&buffer,n);
  87.     }
  88.     put(&buffer,OVER);
  89.     printf("producer stopped\n");

  90.     return NULL;

  91. }

  92. void *consumer(void *data)
  93. {
  94.     int d = 0;
  95.     while(1)
  96.     {
  97.         printf("consumer sleep 2 second...\n"); //每2秒消费一个产品
  98.         sleep(2);
  99.         d = get(&buffer);
  100.         printf("get the %d product\n",d);
  101.         if(d ==OVER)
  102.         {
  103.             break;
  104.         }
  105.     }
  106.     
  107.     printf("consumer stopped\n");
  108.     return NULL;
  109. }

  110. int main(int argc, char *argv[])
  111. {
  112.     pthread_t th_a,th_b;
  113.     void *retval;
  114.     
  115.     init(&buffer);
  116.     
  117.     pthread_create(&th_a, NULL, producer, 0);
  118.     pthread_create(&th_b, NULL, consumer, 0);

  119.     pthread_join(th_a, &retval);
  120.     pthread_join(th_b, &retval);

  121.     return 0;
  122. }
阅读(2208) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~