C++封装POSIX 线程库(二)条件变量的封装
2016-07-25 20:42
561 查看
C++封装POSIX 线程库(二)条件变量的封装
1.Pthread条件变量简介
条件变量也是线程间同步一个重要的内容,如果说互斥是一个种竞争关系,那么条件变量用于协调线程之间的关系,是一种合作关系。条件变量的应用很多,例如:BlockingQueue,
ThreadPool等。
关于POSIX Pthread简介和示例用法可以参考:
POSIX Pthread 条件变量
2. 条件变量的封装
其实就是对pthread_cond_t和相关函数的封装:
#include <pthread.h> pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//静态初始化 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);//动态初始化 int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); int pthread_cond_destroy(pthread_cond_t *cond);
另外,我们在调用pthread_cond_wait的时候,必须先加锁,需要用到之前
MutexLock的私用成员函数,这里已经在
MutexLock.h中将
class Condition设定为了
MutexLock的一个友元。
//Condition.h #ifndef __CONDITION_H__ #define __CONDITION_H__ #include "MutexLock.h" #include <pthread.h> #include <boost/noncopyable.hpp> #include <assert.h> class MutexLock; class Condition { public: Condition(MutexLock &mutex); ~Condition(); void wait();//封装pthread_cond_wait void notify();//封装pthread_cond_signal void notifyAll();//封装pthread_cond_broadcast private: pthread_cond_t cond_; MutexLock &mutex_; }; #endif
对成员函数分别进行初始化:
//Condition.cpp #include "Condition.h" #include "MutexLock.h" #include <assert.h> Condition::Condition(MutexLock &mutex):mutex_(mutex) { CHECK(!pthread_cond_init(&cond_, NULL));//条件变量初始化 } Condition::~Condition() { CHECK(!pthread_cond_destroy(&cond_));//析构操作 } void Condition::wait() { assert(mutex_.isLocking()); //wait前必须上锁 CHECK(!pthread_cond_wait(&cond_, mutex_.getMutexPtr())); //pthread_cond_wait阻塞时释放锁,返回时会自动加锁 mutex_.restoreMutexStatus(); //还原状态 } void Condition::notify() { CHECK(!pthread_cond_signal(&cond_));//通知等待线程队列中的线程 } void Condition::notifyAll() { CHECK(!pthread_cond_broadcast(&cond_));//通知所有等待线程 }
在网上看到一个名词“惊群效应”,意思就是说
broadcast使用不当,当唤醒所有线程而只有一个线程能够拿到资源,所以关于
broadcast还是要慎用。
关于封装条件变量的一般使用,假设我们要实现简单的容量无限的
BlockingQueue,可以这样写:
MutexLock mutex; Condition cond(mutex); std::deque<int> queue; int dequeue() { MutexLockGurad lock(mutex); while(queue.empty()) { cond.wait();//这一步会释放mutex并进入等待,这两个操作是原子的 //wait()返回后,会自动重新加锁 } assert(!queue.empty()); int top = queue.front(); queue.pop_front(); return top; } void enqueue(int x ) { MutexLockGurad(mutex); queue.push_back(x); cond.notify();//这句也可以移出临界区 }
3. 参考
1.http://www.cnblogs.com/inevermore/p/4008397.html2.《Linux多线程服务端编程—使用muduo网络库》
3.http://blog.csdn.net/zhangxiao93/article/details/51835470
相关文章推荐
- 1019. 数字黑洞 (20)
- ubuntu安装MySQL Connector/C++ from Source
- c++构造函数浅析
- GeekBand C++ 面向对象高级编程(上) 第一周笔记
- C++文件读取操作详解
- C++中隐式转换和显示转换
- Leetcode 31. Next Permutation (Medium) (cpp)
- c语言基础
- C++11新特性:可变参数模板
- C语言开始
- C语言 用free函数释放在堆上申请的空间,这个函数到底做了什么
- c++设计模式之组合模式
- 使用JNI进行Java与C/C++语言混合编程(1)--在Java中调用C/C++本地库
- C语言学习超前期
- C++实现ping功能
- c++ 初学者
- C语言 关键字!!面试常碰到!
- [置顶] C语言做的接鸡蛋小游戏(附源码注释)【原创】
- 指针数组
- C++_lesson_1,命令框编译源文件方法