天天看點

C++封裝POSIX 線程庫(四)使用封裝的線程C++封裝POSIX 線程庫(四)使用封裝的線程

C++封裝POSIX 線程庫(四)使用封裝的線程

本文主要介紹如何使用 C++封裝POSIX 線程庫(一)互斥鎖、C++封裝POSIX 線程庫(二)條件變量的封裝和C++封裝POSIX 線程庫(三)線程的封裝三文中介紹的POSIX Pthread的基本元件(互斥鎖,條件變量和線程)C++封裝的使用。

設計一個場景讓我們用到這三個元件:一共啟動三個線程,其中兩個線程負責互斥地對`count“變量進行increment增量操作,另外一個線程則對count變量進行監視,使用條件變量等待其到達某個值時才喚醒修改count的值。

1. 繼承與重寫run方法

我們封裝了Thread類,并設定成員函數run()為純虛函數,是以我們使用類繼承,并重寫run方法:

//main.cpp
class IncCount : public Thread//增加計數線程
{
    private:
        int id_;
    public:
        IncCount(int id):id_(id){}
        void run()
        {
            for(int i=;i < ;i ++)
            {
                {
                    MutexLockGuard lock(mutex);
                    count++;
                    if (count == )
                    {
                        cond.notify();//通知
                    }
                    //列印資訊友善調試
                    std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;
                }//臨界區
                sleep();//注:sleep不是同步原語,這裡隻是為了友善調試
            }
        }
};
class WatchCount: public Thread//監視線程
{
    private:
        int id_;
    public:
        WatchCount(int id):id_(id){}
        void run()
        {
            MutexLockGuard lock(mutex);//加鎖
            while(count < )//這裡用while防止虛假喚醒
            {
                cond.wait();
            }
            assert(count>=);
            count+=;
            std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;
        }
};
           

2. shared_ptr和多态

用C++封裝Pthread元件讓我們很容易想到多态這個特性,當然我們完全可以這樣寫:

//main.cpp
int main()
{
     WatchCount t1();
       IncCount t2();
       IncCount t3();
       t1.start();
       t2.start();
       t3.start();
       t1.join();
       t2.join();
       t3.join();
       return ;
}
           

如果用多态的話,可以用

vector

來儲存父類指針,并初始化指向子類引用,不過使用

vector<Thread*>

我們時常會有困惑,那就是vector作為棧上變量,其程式結束變量生命期結束,而容器中的指針所指向的對象需要我們手動去

delete

,這樣就會容易出錯。boost庫中提供shared_ptr(c++11已經加入std),可以避免這種記憶體洩露的錯誤:vector生命期結束,

shared_ptr

釋放,對象的引用計數變為0,也就自動釋放資源了。

//main.cpp

{
        vector< shared_ptr<Thread> > t();

        t[].reset(new WatchCount());
        t[].reset(new IncCount());
        t[].reset(new IncCount());
        for(int i=;i<;i++)
        {
            t[i]->start();
        }
        for(int i=;i<;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 =;
class IncCount : public Thread
{
    private:
        int id_;
    public:
        IncCount(int id):id_(id){}
        void run()
        {
            for(int i=;i < ;i ++)
            {
                {
                    MutexLockGuard lock(mutex);
                    count++;
                    if (count == )
                    {
                        cond.notify();
                    }
                    std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;
                }
                sleep();
            }
        }
};
class WatchCount: public Thread
{
    private:
        int id_;
    public:
        WatchCount(int id):id_(id){}


        void run()
        {
            MutexLockGuard lock(mutex);
            while(count < )
            {
                cond.wait();
            }
            assert(count>=);
            count+=;
            std::cout<<"thread : "<<id_<<" count : "<< count << std::endl;
        }
};

int main()
{
    {
        vector< shared_ptr<Thread> > t();

        t[].reset(new WatchCount());
        t[].reset(new IncCount());
        t[].reset(new IncCount());
        for(int i=;i<;i++)
        {
            t[i]->start();
        }
        for(int i=;i<;i++)
        {
            t[i]->join();
        }

    }
    return ;
}
           

3.2Makefile

#Makefile

PROGS =main
CLEANFILES = core core.* *.core *.o temp.* *.out typescript* \
        *.lc *.lh *.bsdi *.sparc *.uw

all :${PROGS}


CXXFLAGS+=-g  -std=c++

main: main.o Thread.o MutexLock.o Condition.o
    ${CXX} ${CXXFLAGS} -o [email protected] $^ -lpthread
    @rm *.o
clean:
    rm -f ${PROGS} ${CLEANFILES}
           

4. 參考

1.《Linux多線程服務端程式設計:使用muduo C++網絡庫》

2.http://www.cnblogs.com/inevermore/p/4008572.html