c++ 封装线程库 1
1.Pthread条件变量简介
条件变量也是线程间同步一个重要的内容,如果说互斥是一个种竞争关系,那么条件变量用于协调线程之间的关系,是一种合作关系。
条件变量的应用很多,例如:BlockingQueue,ThreadPool等。
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_;
};
#endi#include "Condition.#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前必须上锁 assert函数就是用来调试的 assert(exp) 若exp的表达式为假 则程序不执行结束报错 为真则什么也不做!!
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_));//通知所有等待线程
}
注意学习下知识点:!!!
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)
等待条件有两种方式:无条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待,
其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的竞争条件(Race Condition)。
mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),
而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。
在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。
激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个; 而pthread_cond_broadcast()则激活所有等待线程。
=========================================================
在网上看到一个名词“惊群效应”,意思就是说broadcast使用不当,当唤醒所有线程而只有一个线程能够拿到资源,所以关于broadcast还是要慎用。
关于封装条件变量的一般使用,假设我们要实现简单的容量无限的BlockingQueue,可以这样写: BlockingQueue就是阻塞队列 经典到就是生产者消费者模型的实现
MutexLock mutex;
Condition cond(mutex);
std::deque<int> queue; int dequeue()//出列
{
MutexLockGurad lock(mutex);
while(queue.empty())
{
cond.wait();//这一步会释放mutex并进入等待,这两个操作是原子的
//wait()返回后,会自动重新加锁 这个wait就是condition类中封装的 pthread_cond_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();//这句也可以移出临界区 ??????不是特别明白
}
c++ 封装线程库 1的更多相关文章
- c++ 封装线程库 2
1.2线程回收: 首先得知道线程的两个状态: Joinable Detached 简单理解,如果一个线程是joinable的状态,那么这样的线程,就必须使用pthread_join来回收,否则程序结束 ...
- c++ 封装线程库 3
1. 继承与重写run方法 我们封装了Thread类,并设置成员函数run()为纯虚函数,因此我们使用类继承,并重写run方法: class IncCount : public Thread//增加计 ...
- c++ 封装线程库 0
1.互斥锁简介 互斥锁主要用于互斥,互斥是一种竞争关系,用来保护临界资源一次只被一个线程访问. POSIX Pthread提供下面函数用来操作互斥锁. int pthread_mutex_init(p ...
- Linux posix线程库总结
由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 线程的实现,经历了如下发展阶段: Linu ...
- 引擎之旅 Chapter.2 线程库
预备知识可参考我整理的博客 Windows编程之线程:https://www.cnblogs.com/ZhuSenlin/p/16662075.html Windows编程之线程同步:https:// ...
- 【Jetlang】一个高性能的Java线程库
actor Jetlang 提供了一个高性能的Java线程库,该库是 JDK 1.5 中的 java.util.concurrent 包的补充,可用于基于并发消息机制的应用. .net的MS CCR ...
- Boost线程库学习笔记
一.创建一个线程 创建线程 boost::thread myThread(threadFun); 需要注意的是:参数可以是函数对象或者函数指针.并且这个函数无参数,并返回void类型. 当一个thre ...
- 【Node.js 自己封装的库 http_parse, libuv】
[Node.js 自己封装的库 http_parse, libuv] Node.js 介绍:一个网络框架,更多:http://www.oschina.net/p/nodejs 官网:http://no ...
- Arduino线程库ProtoThreads
参考: Arduino线程库ProtoThreads 一个“蝇量级” C 语言协程库
随机推荐
- EZOJ #80
传送门 分析 经典的树型DP 我们记录dp[i][0/1]表示i的子树中到i的长度分别为偶数和奇数的长度和 dp2[i][0/1]则表示不在i的子树中的点到i的长度分别为偶数和奇数的长度和 然后根据边 ...
- Luogu 3302 [SDOI2013]森林
BZOJ 3123 丑陋的常数,BZOJ 19968ms 卡过. 感觉几个思想都挺经典但是挺套路的. 先考虑不连边的情况怎么做,区间第$k$小,想到主席树,每一个结点维护它到根的前缀和,这样子每一次查 ...
- android 设置颜色的三种方法
1.利于系统自带的颜色类 如TextView1.setTextColor(Android.graphics.Color.RED); 2.数字颜色表示法 TextView1.setTextColor(0 ...
- Jquery Accordion 折叠面板
属性 类型 默认值 active Boolean/Number/jQuery/Selector/Element 第一个面板 设定默认显示的面板.设置为 false 时默认不显示面板,需 collaps ...
- 2014年第五届蓝桥杯省赛试题(JavaA组)
1.结果填空 (满分2分)2.结果填空 (满分6分)3.结果填空 (满分7分)4.代码填空 (满分4分)5.代码填空 (满分12分)6.结果填空 (满分12分)7.结果填空 (满分9分)8.程序设计( ...
- javascript 常用兼容fire fox的解决办法
常用兼容fire fox的解决办法 一.js不兼容:1.event不兼容,必须通过参数传递过来: function test(event){ //兼容fire fox var event = even ...
- nginx添加缓存以及判断是否缓存生效
location ~.*\.(js|css|html|png|jpg|gif)$ { expires 3d; } expires 3d; //表示缓存3天 expires 3h; //表示 ...
- 拓扑排序+数学+DP【洛谷P1685】 游览
P1685 游览 题目描述 顺利通过了黄药师的考验,下面就可以尽情游览桃花岛了! 你要从桃花岛的西头开始一直玩到东头,然后在东头的码头离开.可是当你游玩了一次后,发现桃花岛的景色实在是非常的美丽!!! ...
- 10.11cdy考试题
鸣谢cdy math [题目描述] 众所周知, xkj是GH的得意门生, 可是xkj的数学成绩并不是很理想: 每次GH在批评完数学限训做的差的人时, 总会在后面加一句:咱们班还有一位做的最差的同学-- ...
- linux1--常用命令
1.目录结构 2./etc:系统配置文件存放地 比如你的wsgi的配置文件,nginx 3./usr 应用程序存放地 比如你的jdk应用程序存放地 4./root 系统管理员root的家目录 4.1像 ...