欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PV-生产者消费者问题实现

程序员文章站 2022-07-05 08:04:06
...

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
参考:https://en.wikipedia.org/wiki/Semaphore_(programming)#Operation_names
参考:https://blog.csdn.net/xin_hen/article/details/107740479

什么是PV,操作系统学习的时候肯定都做过了解了,不过从概念了解到编码实现,还是有一定程度的差距的;很多时候可能也没有去细考虑过实现,不过有些时候,可能讨论时也会涉及到,去了解实现也是挺好的。

PV概念

PV:PV元语,描述尝试资源申请与资源释放

荷兰语:
			Passeren        			Vrijgeven
			Probeer te verlagen(try to reduce)	Verhogen(increase)
中文:  
			通过/申请尝试减少       		释放/增加
描述:  
			资源申请        			资源释放
			资源减少        			资源增长   
程序:	
			acquire                 release
			wait                    signal

生产者与消费者问题

PV元语用来描述下面这个经典问题:生产者消费者问题:producer-consumer problem。
英语: Producer Consumer
中文: 生产者 消费者

生产者与消费者问题,一个进程生产数据,一个进程接受和使用数据;他们通过一个长度最大值为N的队列进行通信;并遵循一下规则处理:

  1. 队列为空时,消费者需要等待生产者产生数据;
  2. 队列满时,生产者需要等待消费者消费数据;
---from wikipedia
In the producer-consumer problem, one process generates data items, and another process receives and use them; They communicate using a queue of maximum size N and are subject to the following conditions: 
1. the consumer must wait for the producer to produce something if the queue is empty. 
2. the producer must wiat for the consumer to consume something if the queue is full. 

假如使用use, left, useQueue分别表达:

  1. 两个量分别描述队列已有数据的空闲量:used, left;初始化left=N, used=0;
  2. 队列使用并行量为1,单任务访问:useQueue,初始化useQueue=1;

描述生产过程与消费过程:

生产过程/produce:
	P(left);      // 从空闲量里申请一个
	P(useQueue);  // 申请queue使用
    push_data_to_queque(item);
	V(useQueue);  // 释放queue使用
	V(used);      // 向使用量里面释放一个

消费过程/consume:
	P(used);      // 从使用量里面申请一个
	P(useQueue);  // 申请queue使用
    item = pop_data_from_queue();
	V(useQueue);  // 释放queue使用
    V(left);      // 向空闲量中释放一个

问题实现

实现生产者与消费者问题,程序中主要使用信号量semaphore来对应,总的信号量个数代表队列总长度,P代表申请信号量,V代表释放信号量,生产消费过程对应信号量的管理;
在C++20之后有支持std::counting_semaphore通过acquire与release方法,完成信号量申请释放,可以较方便的使用;
而对于当前使用较多的C++11版本,也可以利用std::condition_varible与mutex来实现semaphore信号量的功能:
下面是写的一个类似例子,完成信号量总数的约束,仅供参考

// Owed by: http://blog.csdn.net/chunyexiyu
class SemaphoreCount {
public:
	explicit SemaphoreCount(uint32_t left) : m_left(left), m_used(0){};
	void acquire() {
		std::unique_lock<std::mutex> lock(m_mutex);
		m_cv_acquere.wait(lock, [&](){return m_left > 0;});
		m_left--;
		m_used++;
		m_cv_release.notify_one();
	}
	void release() {
		std::unique_lock<std::mutex> lock(m_mutex);
		m_cv_release.wait(lock, [&](){return m_used > 0;});
		m_used--;
		m_left++;
		m_cv_acquere.notify_one();
	}
private:
	std::condition_variable m_cv_acquere;
	std::condition_variable m_cv_release;
	std::mutex m_mutex;
	uint32_t m_left;
	uint32_t m_used;
};

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)

相关标签: 多线程 C/C++