您的位置:首页 > 编程语言 > C语言/C++

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

2016-12-03 18:18 148 查看
#include "stdafx.h"
#include <stack>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/condition.hpp>
#include <boos
4000
t/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();//等待所有线程线程结束返回
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: