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. SPOJ GSS7 - Can you answer these queries VII

    板的不能再板,链剖+线段树或者是LCT随便维护. 感觉唯一要注意的是跳链的时候要对$x$向上跳和$y$向上跳的情况分开讨论,而不能直接$swap$,因为只有两段接触的端点才能相互合并,而且每一次向上跳 ...

  2. (转)HTML&CSS——background: url() no-repeat 0 -64px;CSS中背景图片定位方法

    http://blog.csdn.net/oscar92420aaa/article/details/51304067 CSS中背景图片的定位,困扰我很久了.今天总算搞懂了,一定要记下来. 在CSS中 ...

  3. ObjectARX杂碎--(学习指南及书籍)

    ---------------------------------------------------------------------------------------------------- ...

  4. 混合APP开发-hybrid 升级流程

    本文来自网易云社区 作者:王贝 目前大多数APP已经应用hybrid进混合开发,这不,我们的gacha APP这个版本已经开始使用hybrid来开发了,hybrid的优势这里就不多说了,这里主要讲一下 ...

  5. 区块链中的密码学(二)-RSA算法分析和实现

    密码学领域中,加密算法主要分为对称加密和非对称加密,随着信息时代安全性要求越来越高,对称加密因为其易被破解的原因逐渐被舍弃.而RSA算法是目前密码学世界中比较流行的非对称加密算法,命名是根据其发明者R ...

  6. cuda by example

    int offset= x+y*dim   x 线程块内的线程索引 y 线程块索引 dim 线程块的维度   tid = threadIdx.x+blockIdx.x*blockDim.x 计算大于或 ...

  7. kuangbin专题十六 KMP&&扩展KMP HDU3068 最长回文

    给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input输入有多组case,不超过120组,每组输入为 ...

  8. 获取3个月前的时间(获取某一天的时间 NSDate) --NSCalendar--NSDateComponents

    -(void)getThreeMonthDate:(NSDate *)mydate { NSLog(@"%@",mydate); //1.创建NSCalendar NSCalend ...

  9. shell操作数组

    #!/bin/bash nums=( ) echo ${#nums[*]} #向数组中添加元素 nums[]="http://c.biancheng.net/shell/" ech ...

  10. javascript 中function(){}(),new function(),new Function(),Function

    和java比起来,javascript真的是松散的无以复加,不过这也让我们在无聊之余,有精力去探讨一些复杂的应用,从而在开发之路上,获得一些新的想法. javascript中的类的构造 javascr ...