在之前的两篇博客当中,我们讲述了线程概念、线程控制和线程安全三部分内容。紧随其后本篇博客内容:我们首先来讲述生产者和消费者模型,来了解一种多线程的设计模式,然后在此基础上讲述上一篇博客剩余的内容:信号量的相关接口并写代码实现。
目录
1.生产者与消费者模型
1.1内容
1.2优点
1.3实现
2.信号量
2.1内容
2.2接口
2.3实现
1.生产者与消费者模型
1.1内容
生产者与消费者模型是一种典型的设计模式(针对典型应用场景的解决方案),针是对存在大量数据产生以及处理的场景的一种设计模式。
在原始的操作当中,将数据的产生和获取放在同一个线程中执行,这样会造成程序的大部分时间都用于数据处理,容易造成数据资源获取不及时而被丢弃。
所以我们可以采用生产者与消费之模型,其本质是:将数据产生和处理分离处理,生产者有生产者线程,消费者有消费者线程。生产者只负责数据的获取,消费者只负责数据的处理,两个线程最终通过一个缓冲区(数据队列)来实现数据交互。
1.2优点
- 解耦合(防止不同函数传递参数内容过于相似);
- 支持忙闲不均(数据资源产生和处理大小可以不同);
- 支持并发;
1.3实现
结合上述内容中生产者与消费者模型的本质,我们主要需要完成的内容便是:实现一个线程安全的阻塞队列和创建生产者和消费者线程。
对上述代码编译并执行便可得到结果如下:
我们可以很直观的看到生产者和消费者模型的作用,即同时兼顾数据的输入和输出。这样我们便可用于大量数据的分解处理,提高数据资源的处理效率。
2.信号量
2.1内容
对于信号量的内容,我们再进程间通信(ipc)-3这篇博客中讨论过,没有阅读过的读者可以点击下面连接进行查看。
Linux进程间通信-3_王大可~的博客-CSDN博客
2.2接口
信号量中的接口函数都是在POSIX标准之下,
信号量变量类型:sem_t,头文件:#include<semaphore.h>。
int sem_init(sem_t *sem, int pshared, int val);
sem_init接口用于信号量初始化,其中sem是我们定义的信号量变量;pshared:0 -- 线程间;!0 -- 进程间(共享内存);val是信号量初始值。
P操作:
int sem_wait(sem_t *sem);
sem_wait是阻塞接口。
int sem_trywait(sem_t *sem);
sem_trywait是非阻塞接口。
int sem_timedwait(sem_t *sem, struct timespec *spec);
sem_timedwait是存在设置时长的阻塞接口。
V操作:
int sem_pos(sem_t *sem);
信号量的销毁:
int sem_destroy(sem_t *sem);
2.3实现
在了解完信号量的内容和相关操作接口时,我们来编写代码实现一个线程安全的环形队列。
最后编译并执行可以得到结果如下所示: