与互斥锁不同,条件变量是用来等待而不是用来上锁的,条件变量本身不是锁!
条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。
条件变量的两个动作:
- 条件不满, 阻塞线程
- 当条件满足, 通知阻塞的线程开始工作
条件变量的类型: pthread_cond_t。
生产者消费者模型:
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
//链表结点
typedef struct _node_t
{
int data;
struct _node_t* next;
}node_t;
node_t* head=NULL;//头节点
//条件变量
pthread_cond_t cond;
//互斥量
pthread_mutex_t mutex;
//创建两个线程 生产者线程 消费者线程
//生产者线程
void* producer(void* arg)
{
node_t* new = NULL;
while(1)
{
//加锁
pthread_mutex_lock(&mutex);
new = malloc(sizeof(node_t));
if(NULL == new)
{
printf("malloc failed...\n");
break;
}
memset(new,0,sizeof(node_t));
//1-100
new->data = random()%100 + 1;
new->next = NULL;
printf("生产者生产产品%d\n",new->data);
//头插法
new->next=head;
head=new;
//解锁
pthread_mutex_unlock(&mutex);
//唤醒因为条件变量而阻塞的线程
pthread_cond_signal(&cond);
sleep(random()%3+1);//随机睡眠
}
pthread_exit(NULL);
}
//消费者线程
void* customer(void* arg)
{
node_t* tmp = NULL;
//循环消费
while(1)
{
pthread_mutex_lock(&mutex);
if(NULL == head)
{
//printf("产品链表为空...先休息两秒钟...\n");
//若链表为空 就阻塞
pthread_cond_wait(&cond,&mutex);
}
else
{
tmp = head;
head = head->next;
printf("消费者消耗产品%d\n",tmp->data);
free(tmp);
//解锁
pthread_mutex_unlock(&mutex);
sleep(random()%3+1);
}
}
pthread_exit(NULL);
}
int main()
{
pthread_t = tid1=-1,tid2=-1;
//设置随机种子
srandom(getpid());
//初始化条件变量
ret = pthread_cond_init(&cond,NULL);
if(0 != ret)
{
printf("pthread_cond_init failed...\n");
return 1;
}
//初始化互斥量
ret = pthread_mutex_init(&mutex,NULL);
if(0 != ret)
{
printf("pthread_mutex_init failed...\n");
return 1;
}
pthread_create(&tid1,NULL,producer,NULL);//创建生产者线程
pthread_create(&tid2,NULL,customer,NULL);//创建消费者线程
//等待两个线程结束,回收线程资源
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
//销毁
pthread_cond_destroy(&cond);
pthread)_mutex_destroy(&mutex);
return 0;
}