首页 > 学院 > 开发设计 > 正文

浅析muduo库中的线程设施01

2019-11-08 03:02:06
字体:
来源:转载
供稿:网友

muduo是目前在学习过程中遇到的最具有学习意义的网络库,下文将分析muduo库中的基础设施–Thread和ThreadPool.文中观点如果部分不符合您的理解,请留言指教,谢谢~ 首先,介绍在多线程编程中不可缺少的同步措施–Mutex和Condition.

Mutexclass MutexLock : boost::noncopyable{ public: MutexLock()//创建一个mutex : holder_(0) { MCHECK(pthread_mutex_init(&mutex_, NULL));//MCHECK是muduo提供的宏定义检验函数 } ~MutexLock() { assert(holder_ == 0); MCHECK(pthread_mutex_destroy(&mutex_));//销毁mutex } // must be called when locked, i.e. for assertion bool isLockedByThisThread() const//是否被当前线程锁住 { return holder_ == CurrentThread::tid();//防止跨线程调用 } void assertLocked() const { assert(isLockedByThisThread()); } // internal usage void lock() { MCHECK(pthread_mutex_lock(&mutex_));//加锁 assignHolder();//加锁时获得当前线程的线程号,即当前线程拥有这个锁 } void unlock() { unassignHolder();//表示目前没有线程拥有这个锁 MCHECK(pthread_mutex_unlock(&mutex_));//去锁 } pthread_mutex_t* getPthreadMutex() /* non-const */ { return &mutex_; } PRivate: friend class Condition;//条件变量必须持有了锁之后才能使用 class UnassignGuard : boost::noncopyable//防止条件变量在占有这个锁的时候,锁被销毁;将holder_设置为0,则既不能被其他线程调用也不能被当前线程销毁 { public: UnassignGuard(MutexLock& owner) : owner_(owner) { owner_.unassignHolder(); } ~UnassignGuard()//表示锁被释放 { owner_.assignHolder(); } private: MutexLock& owner_; }; void unassignHolder() { holder_ = 0; } void assignHolder() { holder_ = CurrentThread::tid(); } pthread_mutex_t mutex_; pid_t holder_;}; }//该类负责管理互斥量的加锁和解锁class MutexLockGuard : boost::noncopyable{ public: explicit MutexLockGuard(MutexLock& mutex) : mutex_(mutex)//加锁 { mutex_.lock(); } ~MutexLockGuard() { mutex_.unlock(); } private: MutexLock& mutex_;};

有四种操作互斥锁的方式:创建,销毁,加锁,解锁。在muduo中,用一个低级的资源管理类MutexLock来实现这四种操作,再用一个较高级的资源管理类MutexLockGuard来管理MutexLock,即用RAII手法对资源进行两次封装,防止资源泄漏。

两个类都具有nocopy的属性,试想对Mutex的拷贝会在多线程程序中造成什么样的结果?有至少两个线程在同一时间拥有对一份资源的使用资格,后果不可设想。

在MutexLock中有一个好玩的私有变量:holder_. 该变量在一个线程对资源加锁时,将holder_设置为使用资源线程的索引;解锁时将holder_设置为0。初始化Mutex时将holder_设置为0;销毁时检查holder_是否为0。以上四个步骤保证了Mutex在某一个时间段内能被一个线程使用。

MutexLock与Condition是友元关系,具有很强的耦合度。

Conditionclass Condition : boost::noncopyable{//等待时需要占有互斥量,发送信号时不需要占有互斥量 public: explicit Condition(MutexLock& mutex) : mutex_(mutex) { MCHECK(pthread_cond_init(&pcond_, NULL)); }//不抛出异常的构造那函数,以及初始化条件变量 ~Condition()//销毁条件变量 { MCHECK(pthread_cond_destroy(&pcond_)); } void wait()//使用之前需要占有互斥量 { MutexLock::UnassignGuard ug(mutex_);//目前条件变量所在关联的Mutex不被当前线程所持有 MCHECK(pthread_cond_wait(&pcond_, mutex_.getPthreadMutex())); } // returns true if time out, false otherwise. bool waitForSeconds(double seconds);//等待一定时间的wait void notify() { MCHECK(pthread_cond_signal(&pcond_));//通知一条线程 } void notifyAll()//通知所有的线程 { MCHECK(pthread_cond_broadcast(&pcond_)); } private: MutexLock& mutex_; pthread_cond_t pcond_;};

条件变量有五种操作方式:创建,销毁,等待,单一通知,全部通知。

在MutexLock中有一个内部类:UnassignGuard,该类的实例对象在Condition等待时创建,将holder_设置为0;当等待事件结束,又将holder_设置为原值。用MutexLock的析构函数检查等待事件是否发生在同一个线程中。目的是为了互斥量被意外的销毁。

Condition类中有一个waitForSecond函数,用于实现pthread_cond_timewait的封装。  条件变量在等待时需要持有互斥锁,但是在通知的时候不需要持有锁。


上一篇:算典03_习题_10_UVA-1587

下一篇:可见性

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表