多线程------消费者模式

话说之前说的条件变量是为了做同一件事情的时候,能够让某些关键的数据和节点只能单线程处理,以此来减少关键数据的处理错误。但是一般的多线程处理的事情往往是具有连续性的。比如:
有一个疯狂的水库管理员,一边防水一边加水。但是他比数学书上的疯狂管理员还恶心,他有很多进水口和出水口,并且他还是哪吒的小儿子,所以可以同时打开多个水阀。然后他说,他既要省电也要省水。所以,水池里面的水不能够满,水池水干了时候,不能再出水。
好吧,前面的就是问题描述,实在是有点蛋疼吧。但是我想说的是,这种事情,如果要强行开多线程去解决的话,其实输出结果也是很麻烦的,待会儿各位看看就知道了。其实呢,说老实话这种东西我来做的话,就这样,一次只能一个进水和一个出水。然后每次进水都要通知可以出水了,满了之后进行等待。每次出水之后,都要通知可以进水,如果发现没有水了,要等待注水。
其实,博主说到这里自己也很模糊了,也有点说不清 了。毕竟这东西很麻烦,待会儿我给大家讲讲输出结果,不然大家一定要喷我了。
// boost_concurrent_programming2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#define BOOST_HAS_WINTHREADS
#define BOOST_THREAD_BUILD_DLL
#define BOOST_DATE_TIME_SOURCE
#define BOOST_THREAD_NO_LIB
//#define BOOST_THREAD_USE_LIB 

#include
extern "C" void tss_cleanup_implemented(void){}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//这里的cond_put,cond_get是以boost::condition variance   any为原型进行声明的。其实就是一个触发性的变量,就是它可以触发其他事件的发生,或者等待其他线程触发自己。
boost::mutex io_mu;//io互斥量
class buffer
{
private:
boost::mutex   mu; //这个互斥量是为了关键数据的读取只能单线程操作
boost::condition_variable_any   cond_put;//这个buffer可以流入,也可以流出,所以说,需要两个条件变量。这两个条件变量相互触发,流入数据之后通知别人取,取完之后通知别人流入数据
boost::condition_variable_any cond_get;//
std::stack stk;//这里是数据存储的形式
size_t un_read,capacity;//un_read就是buffer里面及时的数据size,capacity就是buffer的最大内存,
bool is_full()
{
return un_read==capacity;//数据是否满了
}
bool is_empty()
{
return un_read==0;//数据是否empty
}
public:
buffer(size_t n):un_read(0),capacity(n){}//构造函数
void put(int x)
{
{
boost::mutex::scoped_lock lock(mu);//这里需要关键数据的操作,所以说必须设立互斥量
while(is_full())
{
{
boost::mutex::scoped_lock lock(io_mu);//io互斥量
std::cout<<"full waiting...."<<std::endl;
}
cond_put.wait(mu);//这里很重要,如果数据已经满了,这个线程就不用再等了,而是将互斥量解开,并且线程进入睡眠。试想一下如果这里不降互斥量解开是什么后果?这里的互斥量锁住的是关键数据,所以,如果这里不解锁,并且进入睡眠,数据缓冲就是一直满的。
}
stk.push(x);//如果不是满的,再存入数据
++un_read;
}
cond_get.notify_one();//这一步也很重要,当我注入数据之后,必须要通知其他线程来取。因为取的线程有可能现在正在睡眠(如果之前数据缓冲是空的),如果这里你不通知get的线程,get的线程就会一直等到天荒地老都得不到通知
}
void get(int *x)
{
{
boost::mutex::scoped_lock lock(mu);//关键数据的互斥量
while(is_empty())
{
{
boost::mutex::scoped_lock lock(io_mu);
std::cout<<"empty waiting...."<<std::endl;
}
cond_get.wait(mu);//解锁mu,并使这个线程进入睡眠队列.这里也是一样的,如果缓冲里面是空的,那么就要解锁变量,并且让自己进入睡眠。如果有新的数据注入,就要通知它,将它唤醒。
}
--un_read;
*x=stk.top();
stk.pop();
}
cond_put.notify_one();//没取一次都要进行一次唤醒,为了防止那些因为缓冲满了的线程还保持继续睡眠
}


};
buffer buf(5);
void producer (int n)
{
for(int i=0;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
{
buf.get(&x);
boost::mutex(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();//boost里面主要用的join有两种,一种就是join,一种就是join_time(等待一段时间,无论线程是否完成都将线程kill掉).这里用jion的主要原因就是在于,这里程序线程执行的时间会比较长,所以如果不等待线程结束就返回的话,那么进程有可能直接返回了,导致系统将进程中的资源全部收回,导致异常。
t2.join();
t3.join();

return 0;
}
程序结果:
多线程------消费者模式

多线程------消费者模式

多线程------消费者模式
这里的输出可能大家看的很迷糊,但是我希望大家认真想一想这是为什么。。。。。。。。认真想一想哈
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值