c++ 封装线程库 1

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();//这句也可以移出临界区   ??????不是特别明白
}

原文地址:https://www.cnblogs.com/zhangkele/p/9368110.html

时间: 2024-10-20 11:13:36

c++ 封装线程库 1的相关文章

Linux posix线程库总结

由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 目前,pthreads的实现有3种方式: (1)第一,多对一,也就是库实现. (2)第二种,1:1模式. 1:1模式适合CPU密集型的机器.我们知道,进程(线程)在运行中会由于等待某种资源而阻塞,可能是I/O资源,也可能是CPU.在多CPU机器上1:1模式是个很不错的选择.因此1:1的优点就是,能够充分发挥SMP的优势. 这种模式也有它的缺

使用delphi 开发多层应用(十六)使用XMLRPC 实现basic4android 远程调用RTC服务(讲述了RTC的特点,其底层通讯协议是自己封装SOCK 库,与kbmmw 的适合场合不完全一样)

    RealThinClient (以下简称RTC) 也是一款delphi 多层开发的框架,由于其底层通讯协议是自己封装SOCK 库,抛弃了 大家诟病的indy,因此表现的非常稳定,效率也非常高,深受很多人的追捧.由于RTC 是从底层通讯做起的,因此通讯层的 功能非常强,但是在中间层数据库功能虽然有所实现,但是没有kbmmw 和RO 强,但是对于普通的远程调用做的非常优雅. 同时它重点在于使用http 协议实现功能调用,因此与kbmmw 的适合场合不完全一样. 由于RTC 可以非常快速的建立

【C/C++学院】0802-链式栈/链表队列以及优先队列/封装链表库

链式栈 // stacklinknode.h #define datatype int struct stacknode { int num;//编号 datatype data;//数据 struct stacknode *pNext;//指针域 }; typedef struct stacknode StackNode;//简化 StackNode * init(StackNode * phead);//初始化 StackNode * push(StackNode * phead, int

boost 线程库

http://www.boost.org/Boost的安装step1.从www.boost.org下载boost库 step2 在 tools\build\jam_src目录下 运行build.bat来生成jamstep3 设置环境变量(后面的%PATH%要加) PATH=%boost的绝对路径%\tools\build\jam_src\bin.ntx86;%PATH% PATH=%boost的绝对路径%;%PATH% For Visial Studio 6.0SET MSVC_ROOT="VC

linux线程库

linux 提供两个线程库,Linux Threads 和新的原生的POSIX线程库(NPTL),linux threads在某些情况下仍然使用,但现在的发行版已经切换到NPTL,并且大部分应用已经不在加载linux threads,NPTL更轻量,更高效,也会有那些linux threads遇到的问题. 问题:怎么查看系统正在使用哪种线程库呢? linux线程库

c++封装线程类

在csapp学习或者其他linux底层编程的过程中,一般都会举一些多线程或多进程的例子,配合底层同步原语.系统调用api来解释怎么创建多线程/多进程. 但是这些例子和实际项目中所用到的多线程/多进程编程知识有很大的距离(小例子很好理解,但是为了完成一个任务基本就没有什么思路了). 我学习多线程/多进程编程由4个月了,一开始就知道由线程池实现的问题(面试现场白板撸代码的),可是怎么都实现不了, 这一次说什么都要学会(那怕是从别的blog中抄来的代码,直到解释的通就行.加油!!). c++封装线程类

Java高性能线程库:Jetlang

Jetlang 提供了一个高性能的Java线程库,该库是 JDK 1.5 中的 java.util.concurrent 包的补充,可用于基于并发消息机制的应用.该类库不提供远程的消息功能,其设计的宗旨是实现一个内存中的消息传递机制: 主要特点有: All messages to a particular Fiber are delivered sequentially. Components can easily keep state without synchronizing data ac

Arduino线程库ProtoThreads

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

用户态线程库——C语言实现

轮子年年有人造,我们也来凑热闹,参考协程实现,大概有以下几种方法: 1)利用setjmp,longjmp 2)利用ucontext接口函数 3)汇编 (线程无非就是多了个抢占功能,由定时器触发,而非自愿让出运行权限) 因为我写的时候还没看到其他帖子,如果看到了,铁定会用最直观的ucontext接口写的(注意,在macOSX中已经标注为废除,头文件得换做sys/ucontext.h),结果就是我用了汇编来写,但是尽量不用汇编来写整个switch_to调度函数(这样有个明显的坏处,那就是用gas/n