前言
大家好吖,欢迎来到 YY 滴Linux系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁
主要内容含:
欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!
- YY的《C++》专栏
- YY的《C++11》专栏
- YY的《Linux》专栏
- YY的《数据结构》专栏
- YY的《C语言基础》专栏
- YY的《初学者易错点》专栏
- YY的《小小知识点》专栏
- YY的《单片机期末速过》专栏
- YY的《C++期末速过》专栏
- YY的《单片机》专栏
- YY的《STM32》专栏
- YY的《数据库》专栏
- YY的《数据库原理》专栏
目录
- 一.什么是生产者消费者模型
- 二.生产者和消费者各只有一人,缓冲区单元只有一个,用P、V原语实现生产者和消费者的同步操作
- 三.生产者和消费者各只有一人,缓冲区单元有n个,用P、V原语实现生产者和消费者的同步操作
一.什么是生产者消费者模型
生产者消费者问题(Producer-Consumer Problem)通常用于多线程编程中的线程间通信和同步。
- 该问题描述了两个线程(或进程)之间的协作: 一个或多个生产者线程生成数据项,并将它们放入 缓冲区 ;一个或多个消费者线程从 缓冲区 取出数据项,并进行处理。
- 这个过程中,生产者和消费者需要同步,以避免竞争条件和资源冲突。
二.生产者和消费者各只有一人,缓冲区单元只有一个,用P、V原语实现生产者和消费者的同步操作
题目:
- 对于生产者-消费者问题,若缓冲区中缓冲区单元只有一个,生产者和消费者各只有一人。用P、V原语实现生产者和消费者的同步操作
解析:
- 设置两个信号量,
empty full
- 生产者会等待empty,等待缓冲区为空
- 消费者会等待full,等待缓冲区满
- 一开始缓冲区是空的,所以设置时,empty=1,先进去;
Semaphore empty = 1; Semaphore full = 0;
- 生产者线程和消费者线程, 彼此互相唤醒对方的信号量 ,即可
流程图演示:
// 信号量初始化
Semaphore empty = 1; // 缓冲区空闲单元数量
Semaphore full = 0; // 缓冲区已占用单元数量
Buffer buffer; // 缓冲区
// 生产者线程
void producer() {
while (true) {
// 生产一个数据项
item = produceItem();
// 等待缓冲区有空闲单元
P(empty);
// 将数据项放入缓冲区
buffer = item;
// 通知消费者缓冲区中有数据
V(full);
}
}
// 消费者线程
void consumer() {
while (true) {
// 等待缓冲区有数据
P(full);
// 从缓冲区中取出数据项
item = buffer;
// 通知生产者缓冲区中有一个空闲单元
V(empty);
// 消费数据项
consumeItem(item);
}
}
三.生产者和消费者各只有一人,缓冲区单元有n个,用P、V原语实现生产者和消费者的同步操作
题目:
- 对于生产者-消费者问题,若缓冲区中缓冲区的单元有n个,生产者和消费者各只有一个。用P、V原语实现生产者和消费者同步操作。
主干部分解析:
- 设置两个信号量,
empty full
- 生产者会等待empty,等待缓冲区为空
- 消费者会等待full,等待缓冲区满
- 一开始缓冲区是空的,所以设置时,empty=1,先进去;
Semaphore empty = 1; Semaphore full = 0;
- 生产者线程和消费者线程, 彼此互相唤醒对方的信号量 ,即可
改动部分解析:
- 缓冲区单元有n个,所以用 数组 的形式表示缓冲区,
Buffer[n] buffer;
- 设置两个索引
in out
- in 给生产者使用,表示指向下一个空闲缓冲区的索引
- out 给消费者使用,表示指向下一个有数据缓冲区的索引
- 其中,小算法
(in/out+1)%n
实现了循环
流程图演示:
// 信号量初始化
Semaphore empty = n; // 缓冲区空闲单元数量,初始为n
Semaphore full = 0; // 缓冲区已占用单元数量
Buffer[n] buffer; // 大小为n的缓冲区数组
int in = 0; // 指向下一个空闲缓冲区的索引(生产者使用)
int out = 0; // 指向下一个有数据缓冲区的索引(消费者使用)
// 生产者线程
void producer() {
while (true) {
// 生产一个数据项
item = produceItem();
// 等待缓冲区有空闲单元
P(empty);
// 将数据项放入缓冲区
buffer[in] = item;
in = (in + 1) % n; // 循环使用缓冲区
// 通知消费者缓冲区中有数据
V(full);
}
}
// 消费者线程
void consumer() {
while (true) {
// 等待缓冲区有数据
P(full);
// 从缓冲区中取出数据项
item = buffer[out];
out = (out + 1) % n; // 循环使用缓冲区
// 通知生产者缓冲区中有一个空闲单元
V(empty);
// 消费数据项
consumeItem(item);
}
}