C++封装POSIX 线程库(四)使用封装的线程

来源:互联网 发布:linux 监控系统性能 编辑:程序博客网 时间:2024/05/29 06:41

C++封装POSIX 线程库(四)使用封装的线程

本文主要介绍如何使用 C++封装POSIX 线程库(一)互斥锁、C++封装POSIX 线程库(二)条件变量的封装和C++封装POSIX 线程库(三)线程的封装三文中介绍的POSIX Pthread的基本组件(互斥锁,条件变量和线程)C++封装的使用。

设计一个场景让我们用到这三个组件:一共启动三个线程,其中两个线程负责互斥地对`count“变量进行increment增量操作,另外一个线程则对count变量进行监视,使用条件变量等待其到达某个值时才唤醒修改count的值。

1. 继承与重写run方法

我们封装了Thread类,并设置成员函数run()为纯虚函数,因此我们使用类继承,并重写run方法:

//main.cppclass IncCount : public Thread//增加计数线程{    private:        int id_;    public:        IncCount(int id):id_(id){}        void run()        {            for(int i=0;i < 10;i ++)            {                {                    MutexLockGuard lock(mutex);                    count++;                    if (count == 12)                    {                        cond.notify();//通知                    }                    //打印信息方便调试                    std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;                }//临界区                sleep(1.5);//注:sleep不是同步原语,这里只是为了方便调试            }        }};class WatchCount: public Thread//监视线程{    private:        int id_;    public:        WatchCount(int id):id_(id){}        void run()        {            MutexLockGuard lock(mutex);//加锁            while(count < 12)//这里用while防止虚假唤醒            {                cond.wait();            }            assert(count>=12);            count+=125;            std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;        }};

2. shared_ptr和多态

用C++封装Pthread组件让我们很容易想到多态这个特性,当然我们完全可以这样写:

//main.cppint main(){     WatchCount t1(1);       IncCount t2(2);       IncCount t3(3);       t1.start();       t2.start();       t3.start();       t1.join();       t2.join();       t3.join();       return 0;}

如果用多态的话,可以用vector来保存父类指针,并初始化指向子类引用,不过使用vector<Thread*>我们时常会有困惑,那就是vector作为栈上变量,其程序结束变量生命期结束,而容器中的指针所指向的对象需要我们手动去delete,这样就会容易出错。boost库中提供shared_ptr(c++11已经加入std),可以避免这种内存泄露的错误:vector生命期结束,shared_ptr释放,对象的引用计数变为0,也就自动释放资源了。

//main.cpp{        vector< shared_ptr<Thread> > t(3);        t[0].reset(new WatchCount(1));        t[1].reset(new IncCount(2));        t[2].reset(new IncCount(3));        for(int i=0;i<3;i++)        {            t[i]->start();        }        for(int i=0;i<3;i++)        {            t[i]->join();        }}//debug

3. 完整代码

3.1主程序

//main.cpp#include "Thread.h"#include "MutexLock.h"#include "Condition.h"#include  <vector>#include <memory>using namespace std;MutexLock mutex;//互斥锁Condition cond(mutex);//条件变量int count =0;class IncCount : public Thread{    private:        int id_;    public:        IncCount(int id):id_(id){}        void run()        {            for(int i=0;i < 10;i ++)            {                {                    MutexLockGuard lock(mutex);                    count++;                    if (count == 12)                    {                        cond.notify();                    }                    std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;                }                sleep(1.5);            }        }};class WatchCount: public Thread{    private:        int id_;    public:        WatchCount(int id):id_(id){}        void run()        {            MutexLockGuard lock(mutex);            while(count < 12)            {                cond.wait();            }            assert(count>=12);            count+=125;            std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;        }};int main(){    {        vector< shared_ptr<Thread> > t(3);        t[0].reset(new WatchCount(1));        t[1].reset(new IncCount(2));        t[2].reset(new IncCount(3));        for(int i=0;i<3;i++)        {            t[i]->start();        }        for(int i=0;i<3;i++)        {            t[i]->join();        }    }    return 0;}

3.2Makefile

#MakefilePROGS =mainCLEANFILES = core core.* *.core *.o temp.* *.out typescript* \        *.lc *.lh *.bsdi *.sparc *.uwall :${PROGS}CXXFLAGS+=-g  -std=c++11main: main.o Thread.o MutexLock.o Condition.o    ${CXX} ${CXXFLAGS} -o $@ $^ -lpthread    @rm *.oclean:    rm -f ${PROGS} ${CLEANFILES}

4. 参考

1.《Linux多线程服务端编程:使用muduo C++网络库》
2.http://www.cnblogs.com/inevermore/p/4008572.html

1 0