1.Pthread条件变量简介

条件变量也是线程间同步一个重要的内容,如果说互斥是一个种竞争关系,那么条件变量用于协调线程之间的关系,是一种合作关系。

条件变量的应用很多,例如:BlockingQueueThreadPool等。 

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的更多相关文章

  1. c++ 封装线程库 2

    1.2线程回收: 首先得知道线程的两个状态: Joinable Detached 简单理解,如果一个线程是joinable的状态,那么这样的线程,就必须使用pthread_join来回收,否则程序结束 ...

  2. c++ 封装线程库 3

    1. 继承与重写run方法 我们封装了Thread类,并设置成员函数run()为纯虚函数,因此我们使用类继承,并重写run方法: class IncCount : public Thread//增加计 ...

  3. c++ 封装线程库 0

    1.互斥锁简介 互斥锁主要用于互斥,互斥是一种竞争关系,用来保护临界资源一次只被一个线程访问. POSIX Pthread提供下面函数用来操作互斥锁. int pthread_mutex_init(p ...

  4. Linux posix线程库总结

    由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 线程的实现,经历了如下发展阶段: Linu ...

  5. 引擎之旅 Chapter.2 线程库

    预备知识可参考我整理的博客 Windows编程之线程:https://www.cnblogs.com/ZhuSenlin/p/16662075.html Windows编程之线程同步:https:// ...

  6. 【Jetlang】一个高性能的Java线程库

    actor  Jetlang 提供了一个高性能的Java线程库,该库是 JDK 1.5 中的 java.util.concurrent 包的补充,可用于基于并发消息机制的应用. .net的MS CCR ...

  7. Boost线程库学习笔记

    一.创建一个线程 创建线程 boost::thread myThread(threadFun); 需要注意的是:参数可以是函数对象或者函数指针.并且这个函数无参数,并返回void类型. 当一个thre ...

  8. 【Node.js 自己封装的库 http_parse, libuv】

    [Node.js 自己封装的库 http_parse, libuv] Node.js 介绍:一个网络框架,更多:http://www.oschina.net/p/nodejs 官网:http://no ...

  9. Arduino线程库ProtoThreads

    参考: Arduino线程库ProtoThreads 一个“蝇量级” C 语言协程库

随机推荐

  1. Swingr的JTextField、JPasswordField设置圆角输入框

    方法1:定义Border,然后给JTextField设置即可 摘自并整理:https://blog.csdn.net/u012093968/article/details/39316679 最好添加这 ...

  2. Newtonsoft Json操作类库的使用

    1.解析简单Json字符串 if (l_sSenJson != "") { JObject obj2 = (JObject)JsonConvert.DeserializeObjec ...

  3. python运算优先级

    运算符优先级(下面的优先级高) 运算符  描述 lambda  Lambda表达式 or  布尔“或”  and  布尔“与” not x   布尔“非”  in not in 成员测试 is    ...

  4. 读取txt文件将文本行组合成特定格式

    有一网友要求从txt文本文件读取一些数据,然后组合为特定格式的数据行.原论题如下,刚才开始的要求描述得不太清楚,后来补充完整了. Insus.NET觉得本论题可有练习文本件读取功力,因此尝试实现一下. ...

  5. python语言积累

    调试打印堆栈 import traceback traceback.print_exc() #打印堆栈的详细信息

  6. Android camera调用出现错误解决方法

    开发时,先是使用三星的手机测试,发现一切正常: 但是到了小米的手机的时候,发现图片很模糊,发现是设置camera.setParameters(parameters);报错导致用的是默认的最小的分辨率, ...

  7. 解密QQ号

    啊哈~ ---------------------------------------------------------- http://bbs.ahalei.com/thread-4489-1-1 ...

  8. 【转】.net算术运算导致溢出

    源地址:http://blog.csdn.net/hawksoft/article/details/70470136

  9. webpack热更新实现

    原文地址:webpack热更新实现 webpack,一代版本一代神,代代版本出大神.如果你的webpack和webpack-dev-server版本大于2小于等于3.6,请继续看下去.其它版本就必浪费 ...

  10. C语言数据结构-循环队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作

    1.数据结构-循环队列的实现-C语言 #define MAXSIZE 100 //循环队列的存储结构 typedef struct { int* base; //基地址 int _front; //头 ...