生产者和消费者
同步
同步保证了每个执行流可以合理的访问每个临界资源
- 同步的作用
当存在临界资源的时候,就直接获取临界资源;没有资源的时候,进行线程等待,等待其他线程让出临界资源,然后再通知等待线程。
等待线程之间再进行抢占式执行。
条件变量
当一个线程互斥的访问一个变量的时候,可能会出现在其他线程改变状态之前,他自己只能进行等待状态。
如果一个线程的任务是访问一个队列,当他发现这个队列是空的时候,他只能进行等待。等到其他线程将一个节点加入到这个队列中,然后通知等待队列(信号通知),这就要用到条件变量。
- 实现原理
PCB等待队列 + 2个接口(等待接口,唤醒接口)
- 执行流程
1.先判断当前线程有无资源可以利用,没有资源就进行调用等待接口进行线程等待,然后这个等待的线程就会被放在PCB等待队列中挂起等待,直到有其他线程来唤醒PCB等待队列中的线程。
2.当一个执行流生产了一个资源之后,调用唤醒接口。该唤醒接口的执行流就会通知PCB等待队列中被挂起的执行流,通知他们可以去访问临界资源,这些执行流彼此之间再进行抢占式执行
条件变量的接口
1.条件变量的定义
pthread_cond_t
结构体
2.初始化条件变量
#include <pthread.h>
//动态初始化 -- 需要调用销毁接口
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
- cond:传入条件变量的变量地址
- attr:条件变量的属性,一般设置为NULL,让操作系统来默认分配
//静态初始化 -- 不需要调用销毁接口
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
3.等待接口
#include <pthread.h>
//定时等待
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
//一直等待
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
- cond:传入条件变量的变量地址
- mutex:传入互斥锁变量的地址
4.唤醒接口
#include <pthread.h>
//唤醒PCB等待队列中所有执行流
int pthread_cond_broadcast(pthread_cond_t *cond);
//唤醒PCB等待队列中至少一个执行流
int pthread_cond_signal(pthread_cond_t *cond);
- cond:传入条件变量的变量地址
5.销毁条件变量
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
可以释放掉添加变量的内存,防止内存泄漏。
简单实现一个生产者和一个消费者的模型
程序所需要的变量和函数
- 临界资源:g_resource
- 一把互斥锁 lock,一个临界资源 cond
- 生产者线程 tid[1],消费者线程 tid[0]
- 生产者线程任务函数 ProductStart(),消费者线程任务函数 ConsumeStart()
流程图:
代码:
#include <stdio.h>
#include <unistd.h>