muduo网络库源码学习————条件变量
2015-08-29 15:23
519 查看
muduo里的CountDownLatch类实际上是对条件变量condition进行的封装,既可以用于所有子线程等待主线程发起 “起跑” ,也可以用于主线程等待子线程初始化完毕才开始工作。
condition.h代码如下:
condition.cc
CountDownLatch.h
CountDownLatch.cc
测试代码需要自己编写,如下所示,该程序先打印主进程id,建立3个线程,wait等待主线程发号施令,然后睡眠3秒,之后发起号令,打印各个线程的id,代码如下:
由于线程竞争,运行结果不唯一:
另一个结果:
condition.h代码如下:
[code]// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) //条件变量 #ifndef MUDUO_BASE_CONDITION_H #define MUDUO_BASE_CONDITION_H #include <muduo/base/Mutex.h> #include <boost/noncopyable.hpp> #include <pthread.h> namespace muduo { class Condition : boost::noncopyable { public: //构造函数只能显式调用 explicit Condition(MutexLock& mutex) : mutex_(mutex) {//构造函数初始化条件变量 pthread_cond_init(&pcond_, NULL); } //析构函数 ~Condition() {//析构函数销毁条件变量 pthread_cond_destroy(&pcond_); } //等待函数 void wait() { pthread_cond_wait(&pcond_, mutex_.getPthreadMutex()); } // returns true if time out, false otherwise. bool waitForSeconds(int seconds); //signal函数 void notify() { pthread_cond_signal(&pcond_); } //broadcast函数 void notifyAll() { pthread_cond_broadcast(&pcond_); } private: MutexLock& mutex_;//锁,不拥有他,是一个引用,不负责管理他的生存期 pthread_cond_t pcond_;//为一个条件变量 }; } #endif // MUDUO_BASE_CONDITION_H
condition.cc
[code]// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) #include <muduo/base/Condition.h> #include <errno.h> // returns true if time out, false otherwise. bool muduo::Condition::waitForSeconds(int seconds) { struct timespec abstime; clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += seconds; return ETIMEDOUT == pthread_cond_timedwait(&pcond_, mutex_.getPthreadMutex(), &abstime); }
CountDownLatch.h
[code]// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) //对条件变量的封装,既可以用于所有子线程等待主线程发起起跑命令, //也可以用于主线程等待子线程初始化完毕才开始工作 #ifndef MUDUO_BASE_COUNTDOWNLATCH_H #define MUDUO_BASE_COUNTDOWNLATCH_H #include <muduo/base/Condition.h> #include <muduo/base/Mutex.h> #include <boost/noncopyable.hpp> namespace muduo { class CountDownLatch : boost::noncopyable { public: //构造函数,显示调用 explicit CountDownLatch(int count); //等待函数 void wait(); //计数器减 void countDown(); //获取当前计数器的值 int getCount() const; private://mutable表明在const里可以改变他的状态 mutable MutexLock mutex_;//互斥锁 Condition condition_;//条件变量 int count_;//计数器 }; } #endif // MUDUO_BASE_COUNTDOWNLATCH_H
CountDownLatch.cc
[code]// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) #include <muduo/base/CountDownLatch.h> using namespace muduo; //构造函数对值进行初始化,参数为计数器,构造mutex_对象,将mutex_对象传到condition_里面 CountDownLatch::CountDownLatch(int count): mutex_(), condition_(mutex_),count_(count) { } void CountDownLatch::wait() { MutexLockGuard lock(mutex_); //count_不为0则一直等待 while (count_ > 0) { condition_.wait(); } } void CountDownLatch::countDown() { MutexLockGuard lock(mutex_); --count_;//count_减少 if (count_ == 0) {//如果count_为0,则通知所有的等待线程 condition_.notifyAll(); } } int CountDownLatch::getCount() const {//得到count_的值 MutexLockGuard lock(mutex_); return count_; }
测试代码需要自己编写,如下所示,该程序先打印主进程id,建立3个线程,wait等待主线程发号施令,然后睡眠3秒,之后发起号令,打印各个线程的id,代码如下:
[code]#include <muduo/base/CountDownLatch.h> #include <muduo/base/Thread.h> #include <boost/bind.hpp> #include <boost/ptr_container/ptr_vector.hpp> #include <string> #include <stdio.h> //测试程序 using namespace muduo; class Test { public: Test(int numThreads) : latch_(1),threads_(numThreads) {//CountDownLatch对象的计数值初始化为1,线程对象数组的容量初始化为传进来的参数 for (int i = 0; i < numThreads; ++i) {//创建numThreads个线程 char name[32];//线程的名称 snprintf(name, sizeof name, "work thread %d", i); //创建线程,threadFunc为回调函数,因为是成员函数,所以要用&,this为当前类指针 threads_.push_back(new muduo::Thread(boost::bind(&Test::threadFunc, this), muduo::string(name))); } //占位符为参数 for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::start, _1)); } void run() {//count_初始化的时候赋为1,这里只需执行一次既可以跳出等待 latch_.countDown(); } void joinAll() { for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::join, _1)); } private: void threadFunc() { latch_.wait();//等待主线程发号施令 printf("tid=%d, %s started\n", CurrentThread::tid(), CurrentThread::name()); printf("tid=%d, %s stopped\n",CurrentThread::tid(),CurrentThread::name()); } CountDownLatch latch_;//CountDownLatch对象 boost::ptr_vector<Thread> threads_;//线程对象数组 }; int main() {//首先打印当前进程pid,当前线程tid printf("pid=%d, tid=%d\n", ::getpid(), CurrentThread::tid()); //构造Test对象 Test t(3); sleep(3); printf("pid=%d, tid=%d %s running ...\n", ::getpid(), CurrentThread::tid(), CurrentThread::name()); t.run();//发号施令 t.joinAll(); printf("number of created threads %d\n", Thread::numCreated()); }
由于线程竞争,运行结果不唯一:
另一个结果:
相关文章推荐
- ubuntu/centos网络配置
- hdu 4738 2013杭州赛区网络赛 桥+重边+连通判断 ***
- Linux C 网络编程之初探
- Delphi 调用极光推送服务端HTTP API实例
- 非action层获取HttpServletRequest
- c# 下载网络图片到本地
- HTTP状态码
- HTTP Content-type
- Http请求中Content-Type讲解以及在Spring MVC中的应用
- noip2003 神经网络 (拓扑排序,深搜)
- 使用AFNetWorking和ReactiveCocoa对网络请求进行封装(仿煎蛋iOS)(3)
- http 原生post 请求
- Spring中MultipartHttpServletRequest实现文件上传
- TCP.Receiver C# 版本TCP协议接收器 V1.0.03
- HTTP协议
- NS2网络仿真环境的搭建和使用
- c# http get post 用法
- python爬虫 - python requests网络请求简洁之道
- python爬虫 - python requests网络请求简洁之道
- 网络抓包以及进行简单数据分析