• 线程同步--条件变量


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

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

    进程间的同步可以用信号量实现(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 ");
      while(1)
      {

        ListNode *pListNode;
        printf("produce data:%ld ", 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 ");
      while (1)
      {
        pthread_mutex_lock(&mutex);
        while(_list.len < 10)//如果数据小于10个
        {
          printf("consume wait ");
          pthread_cond_wait(&cond, &mutex);//等待信号;先unlock前面的mutex,在收到signal后,重新lock上
          printf("consume wait done ");
          int idx = 0;
          ListNode *node;
          for (idx = 0; idx < 10; idx++)
          {
            node = _list.head;
            list_remove(&_list, node);
            if(node)
            {
              printf("consume data: %d ", 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 ");
      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;
    }

     运行结果如下:

  • 相关阅读:
    mysqldump --skip-tz-utc
    mysql 时间格式转换 DATE_FORMAT
    redis setinel 启动就 sdown
    virtualbox 1059m 布置1G虚拟机
    virtualbox 扩展磁盘空间
    tar gzip 压缩效率比较
    堆表 索引组织表
    内核参数 kernel.shmmax
    utf8mb4 字符集能正常存储表情
    源码包中带 boost 和 不带 boost
  • 原文地址:https://www.cnblogs.com/fellow1988/p/6181374.html
Copyright © 2020-2023  润新知