c++条件变量

条件变量是thread库提供的一种用于等待的同步机制,可以实现线程间的通信,它必须与互斥量配合使用,等待另一个线程中某个事件的发生(满足某个条件),然后线程才能继续执行。

thread库提供两种条件变量对象condition_variable和condition_variable_any,一般情况下,我们应该使用condition_variable_any,它能够适用更广泛的互斥量类型。

用法:拥有条件变量的线程先锁定互斥量,然后循环检查某个条件,如果条件不满足,那么就调用条件变量的成员函数wait()等待直至条件满足。其他线程处理条件变量要求的条件,当条件满足时调用它的成员函数notify_one()或notify_all(),以通知一个或者所有正在等待条件变量的线程停止等待继续执行。

wait():当前线程调用wait()后将被阻塞,直到另外某个线程调用notify_*唤醒当前线程;当线程被阻塞时,该函数会自动调用std::mutex的unlock()释放锁,使得其它被阻塞在锁竞争上的线程得以继续执行。一旦当前线程获得通知(notify,通常是另外某个线程调用notify_*唤醒了当前线程),wait()函数也是自动调用std::mutex的lock()。

生产者-消费者模式:

#include <boost/thread.hpp>
#include <boost/ref.hpp>
#include <iostream>
#include <stack>

boost::mutex io_mu;
class buffer
{
private:
	boost::mutex mu; // 互斥量,配合条件变量使用
	boost::condition_variable_any cond_put; // 写条件变量
	boost::condition_variable_any cond_get; // 读条件变量
	std::stack<int> stk; // 缓冲区对象
	int un_read, capaccity; 
	bool is_full() // 缓冲区满判断
	{
		return un_read == capaccity;
	}
	bool is_empty() // 缓冲区空判断
	{
		return stk.size() == 0;
	}
public:
	buffer(std::size_t n) :un_read(0), capaccity(n){}
	void put(int x) // 写数据
	{
		{ // 开始一个局部域
			boost::mutex::scoped_lock lock(mu); // 锁定互斥量
			while (is_full()) // 检查缓冲区是否满
			{
				{ // 局部域,锁定io_mu
					boost::mutex::scoped_lock lock(io_mu);
					std::cout << "full waiting..." << std::endl;
				}
				cond_put.wait(mu); // 条件变量等待
			} // 条件满足,停止等待
			stk.push(x); // 压栈,写入数据
			++un_read;
		} // 通知前解锁互斥量,条件变量的通知不需要互斥量锁定
		cond_get.notify_one(); // 通知可以读数据
	}

	void get(int *x) // 读数据
	{
		{ // 局部域开始
			boost::mutex::scoped_lock lock(mu); // 锁定互斥量
			while (is_empty()) // 检查缓冲区是否空
			{
				{ // 锁定io_mu
					boost::mutex::scoped_lock lock(io_mu);
					std::cout << "empty waiting..." << std::endl;
				}
				cond_get.wait(mu); // 条件变量等待
			} // 条件满足,停止等待
			--un_read;
			*x = stk.top(); // 读取数据
			stk.pop();
		} // 通知前解锁
		cond_put.notify_one();
	}
};

buffer buf(5); // 定义一个缓冲区对象
void producer(int n) // 生产者
{
	for (int i = 0; i < n; ++i)
	{
		{
			boost::mutex::scoped_lock lock(io_mu);
			std::cout << "put: " << i << std::endl;
		}
		buf.put(i); // 写入数据
	}
}

void consumer(int n) // 消费者
{
	int x;
	for (int i = 0; i < n; ++i)
	{
		{
			buf.get(&x); // 读取数据
			boost::mutex::scoped_lock lock(io_mu);
			std::cout << "get: " << x << std::endl;
		}
	}
}

int main()
{

	boost::thread t1(producer, 20);
	boost::thread t2(consumer, 10);
	boost::thread t3(consumer, 10);
	t1.join();
	t2.join();
	t3.join();
	return 0;
}

  

运行截图:

猜你喜欢

转载自www.cnblogs.com/ACGame/p/9102241.html