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=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.cpp
int 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
#Makefile
PROGS =main
CLEANFILES = core core.* *.core *.o temp.* *.out typescript* \
*.lc *.lh *.bsdi *.sparc *.uw
all :${PROGS}
CXXFLAGS+=-g -std=c++11
main: main.o Thread.o MutexLock.o Condition.o
${CXX} ${CXXFLAGS} -o $@ $^ -lpthread
@rm *.o
clean:
rm -f ${PROGS} ${CLEANFILES}
4. 参考
1.《Linux多线程服务端编程:使用muduo C++网络库》
2.http://www.cnblogs.com/inevermore/p/4008572.html

本文通过实例演示如何使用C++封装的POSIX线程库,包括互斥锁、条件变量和线程的封装。通过三个线程的协同工作,实现对共享变量的安全操作及条件等待。
2449

被折叠的 条评论
为什么被折叠?



