线程同步--条件变量
条件变量可以说是线程同步中运用最多的方式。最常见的是运用在消费者-生产者模型中。
一般由一个线程充当生产者,一个线程充当生产者。消费者需要等到足够量的数据才来消耗数据。在这中间生产者产生数据,并在数据量足够时发信号通知消费者取数据。
进程间的同步可以用信号量实现(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;
}
运行结果如下: