生产者消费者模型

1 问题简介

  生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多进程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
  要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。
  在多线程程序中可能存在资源竞争问题。一般是通过信号量和互斥锁来保证线程安全。

生产者消费者模型_第1张图片

2 C++11实现

  线程安全的生产者和消费者模式。
  具体过程简单的说来就是:当缓冲区空时消费者阻塞,生产者忙;当缓冲区满时,生产者阻塞,消费者忙。

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

template<typename T>
class block_buffer
{
private:
	static const int _size = 20;
	deque<T> _content;
	mutex _mutex;
	condition_variable _con_var;

public:
	block_buffer() = default;
	void enqueue(const T& item)
	{
		unique_lock<mutex> lock(this->_mutex);

		_con_var.wait(lock, [this]() { return this->_content.size() < this->_size; });
		_content.push_back(item);
		_con_var.notify_all();
		cout<<"push item into buffer "<< item<<endl;
	}

	T dequeue()
	{
		unique_lock<mutex> lock(this->_mutex);

		_con_var.wait(lock, [this]() { return this->_content.size() > 0; });
		T item = _content.front();
		_content.pop_front();
		_con_var.notify_all();
		cout<<"delete item from buffer "<<item<<endl;
		return item;
	}
};


template<typename T>
class producer
{
private:
	block_buffer<T> &_buffer;

public:
	producer(block_buffer<T>& buffer)
		: _buffer(buffer)
	{
	}

	void produce()
	{
		while (true)
		{
			T item = produce_function();
			_buffer.enqueue(item);
		}
	}

	int produce_function()
	{
		std::this_thread::sleep_for(std::chrono::seconds(1 + std::rand() % 1));
		int item = std::rand();
		return item;
	}
};

template<typename T>
class consumer
{
private:
	block_buffer<T> &_buffer;

public:
	consumer(block_buffer<T> &buffer)
		: _buffer(buffer)
	{
	}

	void consume()
	{
		while (true)
		{
			T item = _buffer.dequeue();
			consume_function(item);
		}
	}

	void consume_function(int &item)
	{
		std::this_thread::sleep_for(std::chrono::seconds(1 + std::rand() % 2));
	}
};

int main()
{
	block_buffer<int> buffer;
	producer<int> pro_instance(buffer);
	consumer<int> con_instance(buffer);

	thread pro_thread(&producer<int>::produce, &pro_instance);

	thread con_thread(&consumer<int>::consume, &con_instance);

	pro_thread.join();
	con_thread.join();
	return 0;
}

  执行结果。

push item into buffer 18467
delete item from buffer 18467
push item into buffer 26500
delete item from buffer 26500
push item into buffer 15724
push item into buffer 29358
delete item from buffer 15724
push item into buffer 24464
delete item from buffer 29358
push item into buffer 28145
delete item from buffer 24464

你可能感兴趣的:(c++,基础知识)