1. 什么是条件变量?
- 通俗的讲就是当满足某个条件的时候我们就让程序干我们想干的活,条件不满足那就让它阻塞,等到条件满足为止。
2. 什么是互斥锁?
- 互斥锁其实就是用来保护共享资源的一种锁,当多个线程访问共享资源的时候(比如全局数据,堆区开辟的空间)就需要使用互斥锁,才能达到线程同步的效果,这里的同步不是指一起,相同,而是协同的意思,是有先后顺序的。
条件变量函数调用:
- 条件变量初始化函数
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
- 信号发射函数
int pthread_cond_signal(pthread_cond_t *cond);
- 阻塞函数
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
互斥锁函数调用:
- 互斥锁初始化函数
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
- 互斥锁上锁函数
int pthread_mutex_lock(pthread_mutex_t *mutex);
- 互斥锁解锁函数
int pthread_mutex_unlock(pthread_mutex_t *mutex);
介绍完基本概念我们就来看看怎么实现生产者——消费者模型
场景是这样子的:
一个线程不断生产新数据,另一个线程则消费生产出来的数据,比喻成做汉堡,顾客去店里买汉堡。买汉堡肯定要等吧,人多了就更要排队了,所以就必须等到汉堡做出来才能买上,这就是一个生产者,消费者模型。
用代码实现就是首先创建两个线程,一个负责生产,一个负责消费。如果没有生产出来那么就要让消费者等,直到生产出东西来。
demo:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
int g_var = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
//链表节点
typedef struct node
{
int data;
struct node* next;
}Node;
//链表头结点
Node* head = NULL;
void* producer(void* arg)
{
int count = 100;
while(count--)
{
Node* pnew = (Node*)malloc(sizeof(Node));
pthread_mutex_lock(&mutex);
pnew->data = rand()%1000;
printf("producer thread %lu, data %d\n",pthread_self(),pnew->data);
pnew->next = head;
head = pnew;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
usleep(rand()%100);
}
pthread_exit(NULL);
}
void* customer(void* arg)
{
int count = 100;
while(count--)
{
pthread_mutex_lock(&mutex);
if(head == NULL)
{
pthread_cond_wait(&cond,&mutex);
}
//消费
printf("customer thread %lu, data %d\n",pthread_self(),head->data);
Node* pcur = head;
head = head->next;
free(pcur);
pthread_mutex_unlock(&mutex);
usleep(rand()&100);
}
pthread_exit(NULL);
}
int main()
{
//播种
srand(time(NULL));
pthread_t pthid[2];
//初始化互斥锁
pthread_mutex_init(&mutex,NULL);
//初始化条件变量
pthread_cond_init(&cond,NULL);
//创建生产者线程
pthread_create(&pthid[0],NULL,producer,NULL);
//创建消费者线程
pthread_create(&pthid[1],NULL,customer,NULL);
//回收两个线程
pthread_join(pthid[0],NULL);
pthread_join(pthid[1],NULL);
//销毁互斥锁
pthread_mutex_destroy(&mutex);
//销毁条件变量
pthread_cond_destroy(&cond);
pthread_exit(NULL);
}
运行结果:
如果有兴趣的可以尝试写写生产者和多个消费者的场景