线程同步--条件变量

条件变量可以说是线程同步中运用最多的方式。最常见的是运用在消费者-生产者模型中。

一般由一个线程充当生产者,一个线程充当生产者。消费者需要等到足够量的数据才来消耗数据。在这中间生产者产生数据,并在数据量足够时发信号通知消费者取数据。

进程间的同步可以用信号量实现(sem_open时设置信号量初始值为0, sem_wait等待条件满足,sem_post在条件满足后发信号)

先写一个简单的sample来演示这个过程(用队列中的代码稍作修改)

#include <stdlib.h>
#include <stdio.h>

#include <pthread.h>

typedef struct _ListNode{
  struct _ListNode *prev;
  struct _ListNode *next;
  int data;
}ListNode;
typedef struct _List{
  ListNode *head;
  ListNode *tail; 
  int len;

}List;
void list_init(List *pList)
{
  pList->head = NULL;
  pList->tail = NULL;
  pList->len = 0;
}
void list_insert_tail(List *pList, ListNode *node)
{

      if (NULL == pList || NULL == node) return;
  node->next = NULL;
  if ((node->prev = pList->tail) != NULL)
  {
    pList->tail->next = node;
  }
  else
  {
    pList->head = node;
  }
  pList->tail = node;
  pList->len++;
}
void list_remove(List *pList, ListNode* node)
{
  if (pList->tail == node)
  {
    pList->tail = node->prev;
  }
  else
  {
    node->next->prev = node->prev;
  }
  if (pList->head == node)
  {
    pList->head = node->next;
  }
  else
  {
    node->prev->next = node->next;
  }
  if (node != NULL)
  {
    node->prev = node->next = NULL;
  }
}
List _list;
pthread_mutex_t mutex;//最好的方式是将mutex和cond放到List结构体中。
pthread_cond_t cond;
void *produce_thread(void *param)
{
  unsigned long data = 0;
  printf("produce thread\n");
  while(1)
  {

    ListNode *pListNode;
    printf("produce data:%ld\n", data);
    pListNode = (ListNode*)malloc(sizeof(ListNode));
    pListNode->data = data++;
    pListNode->prev = NULL;
    pListNode->next = NULL;
    pthread_mutex_lock(&mutex);
    list_insert_tail(&_list,pListNode);
    if (_list.len >= 10)//如果数据大于10个才发信号
    {
      pthread_cond_signal(&cond);
    }
    pthread_mutex_unlock(&mutex);
    sleep(1);
  }
}

void *consume_thread(void *param)
{
  printf("consume thread\n");
  while (1)
  {
    pthread_mutex_lock(&mutex);
    while(_list.len < 10)//如果数据小于10个
    {
      printf("consume wait\n");
      pthread_cond_wait(&cond, &mutex);//等待信号;先unlock前面的mutex,在收到signal后,重新lock上
      printf("consume wait done\n");
      int idx = 0;
      ListNode *node;
      for (idx = 0; idx < 10; idx++)
      {
        node = _list.head;
        list_remove(&_list, node);
        if(node)
        {
          printf("consume data: %d\n", node->data);
          free(node);
          node = NULL;
        }
      }
      sleep(1);
    }
    pthread_mutex_unlock(&mutex);
  }
}
int main(void)
{
  list_init(&_list);
  pthread_t tid_produce;
  pthread_t tid_consume;
  pthread_mutex_init(&mutex, NULL);
  pthread_cond_init(&cond, NULL);
  printf("start thread\n");
  pthread_create(&tid_produce, NULL, produce_thread, NULL);
  pthread_create(&tid_consume, NULL, consume_thread, NULL);
  while(1);
      pthread_mutex_destroy(&mutex);

      pthread_cond_destroy(&cond);
  return 0;
}

 运行结果如下:

 

posted @ 2016-12-14 22:33  fellow_jing  阅读(362)  评论(0编辑  收藏  举报