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. 杭电ACM刷题(2):1005,Number Sequence 标签: 杭电acmC语言 2017-05-11 22:43 116人阅读

    Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1 ...

  2. Luogu 1357 花园

    发现$m$很小,直接状压起来,可以处理出一开始的合法的状态. 对于每一个合法的状态,可以处理出它的转移方向,即在后面填一个$1$或者填一个$0$,反着处理比较方便. 考虑一下环的情况,在这题中有一个小 ...

  3. 6.Model类

    Basic Concepts      在Model/View结构中,Model提供标准的接口让View和Delegate获得数据.在QT中,标准的接口都被定义在QAbstractItemModel类 ...

  4. Java中抽象类也能实例化.RP

    在Java中抽象类真的不能实例化么? 在学习的过程中,发现了一个问题,抽象类在没有实现所有的抽象方法前是不可以通过new来构建该对象的,但是抽象方法却是可以有自己的构造方法的.这样就把我搞糊涂了,既然 ...

  5. 防恶意解析,禁止用IP访问网站的Apache设置 修改 httpd.conf 实现

    一般来说,网站可以用域名和IP来访问.你的网站可以通过IP直接访问,本来这没什么问题,但是会有些隐患: 由于搜索引擎也会收录你的IP地址的页面,所以同一个页面搜索引擎会重复收录,造成页面的权重不如单个 ...

  6. (数组)字符串的回文构词法( anagrams)

    题目:https://www.nowcoder.com/practice/e84e273b31e74427b2a977cbfe60eaf4?tpId=46&tqId=29130&tPa ...

  7. break跳出多重循环

    大家都知道break只能跳出当前的一个循环语句,如果碰到要跳出多个循环体,那么我们就该在循环体开头设置一个标志位,然后使用带此标志位的break语句跳出多重循环 jump: ;i<;i++){ ...

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

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

  9. es6学习总结一

    一.let与var 的区别 (1).作用域: let什么的变量在块级作用域内有效,而var声明则在全局作用内有效 (2).变量提升: let声明的变量不存在变量提升,即一定要在声明之后才能调用,否则就 ...

  10. unity list循环

    复制的感觉挺有用就保存下来 using System.Collections;using System.Collections.Generic;using UnityEngine; public cl ...