条件变量Condition Variable
一个Condition Variable总是和一个Mutex搭配使用的。一个线程可以调用pthread_cond_wait在一个Condition Variable上阻塞等待,这个函数做以下三步操作:
- 释放Mutex(不满足条件时必须进行休眠)
- 进行阻塞式等待(不能抱着锁资源休眠)
- 被唤醒时能够重新获得Mutex资源并等待(能被唤醒)
基于链表的生产者消费者模型
- 生产者生产好数据之后通知消费者来消费数据
- 消费者消费完数据后通知生产者前来生产
(生产者生产一个随机数在链表的表头上,消费者从表头取⾛随机数)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
typedef struct _listnode
{
struct _listnode* next;
int _val;
}node, *plist, **pplist;
plist head = NULL;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
plist buy_node(int d)
{
plist tmp = (plist)malloc(sizeof(node));
if(!tmp)
{
perror("malloc");
exit(1);
}
tmp->next = NULL;
tmp->_val = d;
return tmp;
}
void init_list(pplist list)
{
*list = buy_node(0);
}
int is_empty(plist list)
{
return list->next == NULL ? 1 : 0;
}
static void free_node(plist list)
{
if(list)
{
free(list);
list = NULL;
}
}
void push_front(plist list, int d)
{
plist tmp = buy_node(d);
tmp->next = list->next;
list->next = tmp;
}
void pop_front(plist list, int *_out)
{
if(!is_empty(list))
{
plist tmp = list->next;
list->next = tmp->next;
*_out = tmp->_val;
free_node(tmp);
}
}
void destroy(plist list)
{
int data = 0;
while(!is_empty(list))
{
pop_front(list, &data);
}
free_node(list);
list = NULL;
}
void display(plist head)
{
plist start = head->next;
while(start)
{
printf("%d ", start->_val);
start = start->next;
}
printf("\n");
}
void *custume()
{
int data = 0;
while(1)
{
pthread_mutex_lock(&lock);
if(is_empty(head))
{
pthread_cond_wait(&cond, &lock);
}
pop_front(head, &data);
//display(head);
printf("custumer custume: %d\n", data);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
sleep(3);
}
}
void *product()
{
while(1)
{
pthread_mutex_lock(&lock);
int data = rand()%1234;
push_front(head,data);
//display(head);
printf("producer product: %d\n", data);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
sleep(1);
}
}
int main()
{
pthread_t custumer, producer;
init_list(&head);
pthread_create(&custumer, NULL, custume, NULL);
pthread_create(&producer, NULL, product, NULL);
pthread_join(custumer, NULL);
pthread_join(producer, NULL);
destroy(head);
return 0;
}