c++ 多线程编程 条件变量

#include "stdafx.h"
#include <stack>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/condition.hpp>
#include <boost/atomic.hpp>
#include <iostream>
#include <boost/thread.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/lock_factories.hpp>
#include <boost/thread/lockable_concepts.hpp>
#include <boost/thread/lockable_concepts.hpp>
#include <boost/thread/thread_guard.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/shared_lock_guard.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/lock_factories.hpp>
#include <boost/thread/scoped_thread.hpp>

using namespace boost;

//冰淇淋商店
class CleamShop
{
private:
	//互斥量(用于控制有多个用户时,每次只有一个用户购买冰淇淋)
	mutex mu;
	//能生产冰淇淋条件变量
	//用于控制只有生产冰淇淋的条件变量得到满足时才能继续执行
	condition_variable_any cond_CanProduct;
	//能购买冰淇淋条件变量
	//用于控制只有购买冰淇淋的条件变量得到满足时才能购买冰淇淋
	condition_variable_any cond_CanBuy;

	std::stack<int> stk;//已经生产好的冰淇淋对象

	int m_nCleamNum,capacity;//生产冰淇淋的上限

	bool is_full()//判断冰淇淋是否满了
	{
		return m_nCleamNum == capacity;
	}

	bool is_empty()//判断是否还有冰淇淋
	{
		return 0 == m_nCleamNum;
	}
public:
	explicit CleamShop(const size_t &n):m_nCleamNum(0),capacity(n){}
	//生产冰淇淋      //冰淇淋的ID
	void ProductCleams(int m_iID)
	{
		do 
		{
			//锁住资源,防止其他用户和生产者操作
			unique_lock<mutex> lock = make_unique_lock(mu);
			//获得当前是哪个生产冰淇淋的生产者在生产
			auto id = this_thread::get_id();
			//std::cout << "Current Productor ID:" << this_thread::get_id() << std::endl;
			while(is_full())
			{
				std::cout << this_thread::get_id() << "冰淇淋生产满了,不能生产了,等待用户购买之后再生产..." << std::endl;
				//满了,不能生产了,等待可以生产这个条件变量的满足
				//否则该生产者就一直在这里等待
				//在函数内部会执行类似的解锁动作以让其他线程
				//得到允许
				//等待cond_CanProduct.NoticeXXX函数之后
				//就可以唤醒继续执行了
				cond_CanProduct.wait(lock);
			}
			//上面的while代码可以用下面这行代码代替
			//cond_CanProduct.wait(lock,!bind(&CleamShop::is_full,this));
			stk.push(m_iID);//生产好了一个冰淇淋
			++m_nCleamNum;
			std::cout << this_thread::get_id() << "Producted." << std::endl;
		} while (0);
		//通知一个用户说:可以购买冰淇淋了
		//即cond_CanBuy条件变量满足了,
		//其他在等待的一个用户线程不需要等待了,可以唤醒换回了
		cond_CanBuy.notify_one();
	}

	void get(int *x)
	{
		do 
		{
			//锁住资源,防止其他用户和生产者操作
			unique_lock<mutex> lock = make_unique_lock(mu);
			//获得当前是哪个消费者线程在购买冰淇淋
			auto id = this_thread::get_id();
			//std::cout << "Current ID:" << this_thread::get_id() << std::endl;
			
			while(is_empty())//没有冰淇淋了
			{
				std::cout << this_thread::get_id() << "没有冰淇淋了,不能购买,等待生产者生产冰淇淋..." << std::endl;
				//没有冰淇淋了,不能购买了
				//等待生产者生产冰淇淋
				//等待能购买冰淇淋的条件得到满足才能购买
				//就是要等待cond_CanBuy.NoticeXXX函数通知
				//就表示可以购买了
				cond_CanBuy.wait(lock);
			}
			//上面的while代码可以用下面这行代码代替
			//cond_CanBuy.wait(lock,!bind(&CleamShop::is_empty,this));
			--m_nCleamNum;
			*x = stk.top();
			stk.pop();//购买了一个冰淇淋
			std::cout << this_thread::get_id() << "Buied." << std::endl;
		} while (0);
		//通知一个生产者线程现在可以生产冰淇淋了
		cond_CanProduct.notify_one();
	}
}; 
//创建一个冰淇淋商店,生产冰淇淋的上限是5个
CleamShop buf(5);

//生产者生产冰淇淋
void producter(int n)//计划生产0-n的冰淇淋
{
	for (int i = 0;i < n;++i)
	{
		//std::cout << this_thread::get_id() << "正在生产冰淇淋:" << i << "..." << std::endl;
		buf.ProductCleams(i);
		//std::cout << this_thread::get_id() << "生产完成冰淇淋:" << i << std::endl;
	}
}
//用户购买冰淇淋
void consumer(int n)//打算购买n个冰淇淋
{
	int x;
	for (int i = 0;i < n;++i)
	{
		//std::cout << this_thread::get_id() << "正在购买冰淇淋..." << std::endl;
		buf.get(&x);
		//std::cout << this_thread::get_id() << "购买到了冰淇淋:" << x << std::endl;
	}
}

void test1()
{
	std::cout << this_thread::get_id() << std::endl;
	thread_group tg;
	tg.create_thread(bind(producter,20));//生产者1,可以生产冰淇淋总数是20个
	tg.create_thread(bind(consumer,10));//用户1,打算购买10个冰淇淋
	tg.create_thread(bind(consumer,10));//用户2,打算购买10个冰淇淋

	tg.join_all();//等待所有线程线程结束返回
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值