Boost Thread学习笔记三
下面先对condition_impl进行简要分析。
condition_impl在其构造函数中会创建两个Semaphore(信号量):m_gate、m_queue,及一个Mutex(互斥体,跟boost::mutex类似,但boost::mutex是基于CriticalSection<临界区>的):m_mutex,其中:
m_queue
相当于当前所有等待线程的等待队列,构造函数中调用CreateSemaphore来创建Semaphore时,lMaximumCount参数被指定为(std::numeric_limits<long>::max)(),即便如此,condition的实现者为了防止出现大量等待线程的情况(以至于超过了long的最大值),在线程因执行condition::wait进入等待状态时会先:
WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
以等待被唤醒,但很难想象什么样的应用需要处理这么多线程。
m_mutex
用于内部同步的控制。
但对于m_gate我很奇怪,我仔细研究了一下condition_imp的实现,还是不明白作者引入m_gate这个变量的用意何在,既然已经有了用于同步控制的m_mutex,再引入一个m_gate实在让我有点不解。
以下是condition::wait调用的do_wait方法简化后的代码:
2 void do_wait(M& mutex)
3 {
4 m_impl.enter_wait();
5 lock_ops::unlock(mutex, state); //对传入的scoped_lock对象解锁,以便别的线程可以对其进行加锁,并执行某些处理,否则,本线程等待的condition永远不会发生(因为没有线程可以获得访问资源的权利以使condition发生)
6 m_impl.do_wait(); //执行等待操作,等待其它线程执行notify_one或notify_all操作以获得
7 lock_ops::lock(mutex, state); //重新对scoped_lock对象加锁,获得独占访问资源的权利
8 }
condition::timed_wait的实现方法与此类似,而notify_one、notify_all仅将调用请求转发给m_impl,就不多讲了。
虽然condition的内部实现比较复杂,但使用起来还是比较方便的。下面是一个使用condition的多Producer-多Consumer同步的例子:
2 #include <boost/thread/mutex.hpp>
3 #include <boost/thread/condition.hpp>
4 #include <boost/thread/xtime.hpp>
5
6 #include <iostream>
7 #include <time.h> // for time()
8
9 #include <Windows.h> // for Sleep, change it for other platform, we can use
10 // boost::thread::sleep, but it's too inconvenient.
11
12 typedef boost::mutex::scoped_lock scoped_lock;
13 boost::mutex io_mutex;
14
15 class Product
16 {
17 int num;
18 public:
19 Product(int num) : num(num) {}
20
21 friend std::ostream& operator<< (std::ostream& os, Product& product)
22 {
23 return os << product.num;
24 }
25 };
26
27 class Mediator
28 {
29 private:
30 boost::condition cond;
31 boost::mutex mutex;
32
33 Product** pSlot; // product buffer/slot
34 unsigned int slotCount, // buffer size
35 productCount; // current product count
36 bool stopFlag; // should all thread stop or not
37
38 public:
39 Mediator(const int slotCount) : slotCount(slotCount), stopFlag(false), productCount(0)
40 {
41 pSlot = new Product*[slotCount];
42 }
43
44 virtual ~Mediator()
45 {
46 for (int i = 0; i < static_cast<int>(productCount); i++)
47 {
48 delete pSlot[i];
49 }
50 delete [] pSlot;
51 }
52
53 bool Stop() const { return stopFlag; }
54 void Stop(bool) { stopFlag = true; }
55
56 void NotifyAll() // notify all blocked thread to exit
57 {
58 cond.notify_all();
59 }
60
61 bool Put( Product* pProduct)
62 {
63 scoped_lock lock(mutex);
64 if (productCount == slotCount)
65 {
66 {
67 scoped_lock lock(io_mutex);
68 std::cout << "Buffer is full. Waiting

69 }
70 while (!stopFlag && (productCount == slotCount))
71 cond.wait(lock);
72 }
73 if (stopFlag) // it may be notified by main thread to quit.
74 return false;
75
76 pSlot[ productCount++ ] = pProduct;
77 cond.notify_one(); // this call may cause *pProduct to be changed if it wakes up a consumer
78
79 return true;
80 }
81
82 bool Get(Product** ppProduct)
83 {
84 scoped_lock lock(mutex);
85 if (productCount == 0)
86 {
87 {
88 scoped_lock lock(io_mutex);
89 std::cout << "Buffer is empty. Waiting

90 }
91 while (!stopFlag && (productCount == 0))
92 cond.wait(lock);
93 }
94 if (stopFlag) // it may be notified by main thread to quit.
95 {
96 *ppProduct = NULL;
97 return false;
98 }
99
100 *ppProduct = pSlot[--productCount];
101 cond.notify_one();
102
103 return true;
104 }
105 };
106
107 class Producer
108 {
109 private:
110 Mediator* pMediator;
111 static unsigned int num;
112 unsigned int id; // Producer id
113
114 public:
115 Producer(Mediator* pMediator) : pMediator(pMediator) { id = num++; }
116
117 void operator() ()
118 {
119 Product* pProduct;
120 srand( (unsigned)time( NULL ) + id ); // each thread need to srand differently
121 while (!pMediator->Stop())
122 {
123 pProduct = new Product( rand() % 100 );
124 // must print product info before call Put, as Put may wake up a consumer
125 // and cause *pProuct to be changed
126 {
127 scoped_lock lock(io_mutex);
128 std::cout << "Producer[" << id << "] produces Product["
129 << *pProduct << "]" << std::endl;
130 }
131 if (!pMediator->Put(pProduct)) // this function only fails when it is notified by main thread to exit
132 delete pProduct;
133
134 Sleep(100);
135 }
136 }
137 };
138
139 unsigned int Producer::num = 1;
140
141 class Consumer
142 {
143 private:
144 Mediator* pMediator;
145 static unsigned int num;
146 unsigned int id; // Consumer id
147
148 public:
149 Consumer(Mediator* pMediator) : pMediator(pMediator) { id = num++; }
150
151 void operator() ()
152 {
153 Product* pProduct = NULL;
154 while (!pMediator->Stop())
155 {
156 if (pMediator->Get(&pProduct))
157 {
158 scoped_lock lock(io_mutex);
159 std::cout << "Consumer[" << id << "] is consuming Product["
160 << *pProduct << "]" << std::endl;
161 delete pProduct;
162 }
163
164 Sleep(100);
165 }
166 }
167 };
168
169 unsigned int Consumer::num = 1;
170
171 int main()
172 {
173 Mediator mediator(2); // we have only 2 slot to put products
174
175 // we have 2 producers
176 Producer producer1(&mediator);
177 boost::thread thrd1(producer1);
178 Producer producer2(&mediator);
179 boost::thread thrd2(producer2);
180 // and we have 3 consumers
181 Consumer consumer1(&mediator);
182 boost::thread thrd3(consumer1);
183 Consumer consumer2(&mediator);
184 boost::thread thrd4(consumer2);
185 Consumer consumer3(&mediator);
186 boost::thread thrd5(consumer3);
187
188 // wait 1 second
189 Sleep(1000);
190 // and then try to stop all threads
191 mediator.Stop(true);
192 mediator.NotifyAll();
193
194 // wait for all threads to exit
195 thrd1.join();
196 thrd2.join();
197 thrd3.join();
198 thrd4.join();
199 thrd5.join();
200
201 return 0;
202 }
Boost Thread学习笔记三的更多相关文章
- Boost Thread学习笔记
thread自然是boost::thread库的主 角,但thread类的实现总体上是比较简单的,前面已经说过,thread只是一个跨平台的线程封装库,其中按照所使用的编译选项的不同,分别决定使用 W ...
- Boost Thread学习笔记五
多线程编程中还有一个重要的概念:Thread Local Store(TLS,线程局部存储),在boost中,TLS也被称作TSS,Thread Specific Storage.boost::thr ...
- Boost Thread学习笔记四
barrierbarrier类的接口定义如下: 1 class barrier : private boost::noncopyable // Exposition only 2 { 3 pub ...
- Boost Thread学习笔记二
除了thread,boost种:boost::mutexboost::try_mutexboost::timed_mutexboost::recursive_mutexboost::recursive ...
- 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记
回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...
- muduo网络库学习笔记(三)TimerQueue定时器队列
目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- [Firefly引擎][学习笔记三][已完结]所需模块封装
原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读: 笔记三主要就是各个模块的封装了,这里贴 ...
- JSP学习笔记(三):简单的Tomcat Web服务器
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
随机推荐
- 如何用 new 来动态开辟一个二维数组
一般的做法是: int **p = new int*[m]; //m行n列型 for (i = 0; i < m; ++i) { p[i] = new int[n]; for (j = 0; j ...
- ZOJ 3607 Lazier Salesgirl 贪心
这个题比上个题简单得多,也是超过W时间会睡着,睡着就再也不会卖了,顾客按时间顺序来的,但是可能有顾客同时到(同时到如果醒着就全卖了),并且每个人只买一块面包,也是求最大的W,使得卖出面包的平均价格最高 ...
- Android使用HttpClient向服务器传输文件
HttpClient是Apache Jakarta Common下的子项目,可以用来提供功能丰富的支持HTTP协议的客户端编程工具包,这几天写客户端的时候遇到个问题,“客户端需要向服务器发送Post请 ...
- jquery ajax json 数据的遍历
需求:进行ajax请求后,后台传递回来以下json数据 { "data":[ {","name":"选择A","valu ...
- java之Thread.sleep(long)与object.wait()/object.wait(long)的区别(转)
一.Thread.sleep(long)与object.wait()/object.wait(long)的区别sleep(long)与wait()/wait(long)行为上有些类似,主要区别如下:1 ...
- 海量数据处理算法—Bloom Filter
海量数据处理算法—Bloom Filter 1. Bloom-Filter算法简介 Bloom-Filter,即布隆过滤器,1970年由Bloom中提出.它可以用于检索一个元素是否在一个集合中. Bl ...
- 2013年最好的Python开源项目汇总
2013年Python社区诞生了很多实用的开发工具,这些工具 在一定程度上 可以帮助你节省更多的时间.本文为你汇总了这些工具,它们大部分都是开源的,你还可以通过源码来学习更多的Python开发知识. ...
- Java网络蜘蛛/网络爬虫 Spiderman
Spiderman - 又一个Java网络蜘蛛/爬虫 Spiderman 是一个基于微内核+插件式架构的网络蜘蛛,它的目标是通过简单的方法就能将复杂的目标网页信息抓取并解析为自己所需要的业务数据. 主 ...
- [置顶] CSS+DIV总结
HTML在Web飞速发展的过程中起着重要作用,有着重要地位.HTML初衷是为了表达标签(<p>.<table>)的内容信息.同时文档布局由浏览器来完成,不使用任何格式 ...
- 自定义类似QMutexLocker的CMutexLocker
最近做项目遇到一个需求,有一个buttonSlot()执行要耗点时间,为了防止用户无限制的乱点出现问题,考虑加一个互斥锁,使得每次执行完后才允许执行下一次.大概意思是: //QMutex m_mut ...