在上章节我们使用读写锁效率已经变得相对高了,这里介绍一个模型---------生产者与消费者模型
什么是生产者与消费者模型呢?学过操作系统这门课的人们都应该记得线程的调度的时候有一个”生产者与消费者“模型,在我们多线程这里其实也是一样的
严格意义上来说,条件变量的主要作用不是处理线程同步,而是进行线程的阻塞。如果在多线程程序中只使用条件变量无法实现线程的同步,必须要配合互斥锁来使用。虽然条件变量和互斥锁都能阻塞线程,但是二者的效果是不一样的,二者的区别如下:
假设有 A-Z 26 个线程,这 26 个线程共同访问同一把互斥锁,如果线程 A 加锁成功,那么其余 B-Z 线程访问互斥锁都阻塞,所有的线程只能顺序访问临界区
条件变量只有在满足指定条件下才会阻塞线程,如果条件不满足,多个线程可以同时进入临界区,同时读写临界资源,这种情况下还是会出现共享资源中数据的混乱。
生产者生产出资源的时候消费者出消费,同时消费者和生产者的操作都是串行操作的,现在我们来举一个例子来进一步了解这个模型
生产者有 5 个,往链表头部添加节点,消费者也有 5 个,删除链表头部的节点。
#include<stdio.h>
#include<pthread.h>
#include <stdlib.h>
pthread_mutex_t mutex;
pthread_cond_t my_cond;
typedef struct Node
{
int num;
struct Node *next;
}node;
node *head=NULL;
void *produce(void *argv);
void *consumer(void *argv);
int main(void)
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&my_cond,NULL);
pthread_t pro[5],con[5];
for(int i=0;i<5;i++)
{
pthread_create(&pro[i],NULL,produce,NULL);
pthread_create(&con[i],NULL,consumer,NULL);
}
for(int i=0;i<5;i++)
{
pthread_join(pro[i],NULL);
pthread_join(con[i],NULL);
}
pthread_cond_destroy(&my_cond);
pthread_mutex_destroy(&mutex);
return 0;
}
void *produce(void *argv)
{
while(1)
{
pthread_mutex_lock(&mutex);
node * n=(node*)malloc(sizeof(struct Node));
n->num=rand()%10;
n->next=head;
head=n;
printf("produce %ld, num =%d\n",pthread_self(),n->num);
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&my_cond);
sleep(rand()%5);
}
return NULL;
}
void *consumer(void *argv)
{
while(1)
{
pthread_mutex_lock(&mutex);
while(head==NULL)
{
pthread_cond_wait(&my_cond,&mutex);
}
//pthread_mutex_lock(&mutex);
node * my_node=head;
printf("consumer id=%ld ,num=%d\n",pthread_self(),my_node->num);
head=head->next;
free(my_node);
pthread_mutex_unlock(&mutex);
sleep(rand()%3);
}
}
思路分析:
其实这个是和我们之前的操作是类似的,不同的是在生产者生产了资源之后就通知消费者去消费,消费者判断如果有资源就消费,没有资源就阻塞,当生产者通知它的时候再去消费
这里有几个函数
pthread_cond_wait(&cond, &mutex);
函数原型 int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);//阻塞函数,没有资源的时候 阻塞
pthread_cond_broadcast(&cond);
函数原型 int pthread_cond_broadcast(pthread_cond_t *cond);//
这里我们重点在于阐述生产者和消费者的模型,所以关于链表的操作就不赘述了,有疑问的同学可以产看博主之前的文章C语言----链表的操作