面向对象版本:使用纯虚函数+继承实现动态多态
有点缺陷:没有设置线程类对象、互斥锁对象、条件变量对象为不可复制
Condition.hpp
#ifndef __CONDITION__H__
#define __CONDITION__H__
#include <pthread.h>
namespace my
{
class MutexLock;//前向声明
class Condition {
public:
~Condition();
Condition(MutexLock & mutex);
void wait();
void notify();//唤醒一个线程
void notifyall();//唤醒全部线程
pthread_cond_t * getCondPtr();
private:
MutexLock & _mutex;
pthread_cond_t _cond;
};
}
#endif
Condition.cc
#include "Condition.hpp"
#include "MutexLock.hh"
#include <iostream>
namespace my
{
Condition::~Condition()
{
if(pthread_cond_destroy(getCondPtr()) != 0)
{
perror("pthread_cond_destroy");
}
}
Condition::Condition(MutexLock & mutex)
:_mutex(mutex)
{
if(pthread_cond_init(getCondPtr() , nullptr) != 0)
{
perror("pthread_cond_init");
}
}
void Condition::wait()
{
if(pthread_cond_wait(getCondPtr() , _mutex.getMutexPtr()) != 0)
{
perror("pthread_cond_wait");
}
}
void Condition::notify()//唤醒一个线程
{
if(pthread_cond_signal(getCondPtr()) != 0)
{
perror("pthread_cond_signal");
}
}
void Condition::notifyall()//唤醒全部线程
{
if(pthread_cond_broadcast(getCondPtr()) != 0)
{
perror("pthread_cond_broadcast");
}
}
pthread_cond_t * Condition::getCondPtr()
{
return &_cond;
}
}
MutexLock.hh
#ifndef __MUTEXTLOCK__H__
#define __MUTEXTLOCK__H__
#include <pthread.h>
namespace my
{
class MutexLock {
public:
~MutexLock();
MutexLock();
pthread_mutex_t * getMutexPtr();
void lock();
void unlock();
private:
pthread_mutex_t _mutex;//互斥锁
};
}//end of nanmespace my
#endif
MutexLock.cc
#include "MutexLock.hh"
#include <iostream>
namespace my
{
MutexLock::MutexLock()
{
if(pthread_mutex_init(getMutexPtr(), nullptr) != 0)
{
perror("pthread_mutex_init");
}
}
MutexLock::~MutexLock()
{
if(pthread_mutex_destroy(getMutexPtr()) != 0)
{
perror("pthread_mutex_destroy");
}
}
void MutexLock::lock()
{
if(pthread_mutex_lock(getMutexPtr()) != 0)
{
perror("pthread_mutex_lock");
}
}
void MutexLock::unlock()
{
if(pthread_mutex_unlock(getMutexPtr()) != 0)
{
perror("pthread_mutex_unlock");
}
}
pthread_mutex_t * MutexLock::getMutexPtr()
{
return &_mutex;
}
}
thread.hh
#ifndef __THREAD_H__
#define __THREAD_H__
#include <pthread.h>
namespace my
{
class Thread {
public:
void start();//创建线程
void join();//等待线程退出
virtual ~Thread();//设为虚函数:防止派生类资源清理不干净
Thread();
private:
static void * threadFun(void* p);//线程执行函数
virtual void run()=0; //线程需要实现的任务
pthread_t _pThid;//线程ID
bool _isRunning;//标识线程是否在运行
};
}
thread.cc
#include "thread.hh"
#include <iostream>
namespace my
{
void Thread::start()//创建线程
{
if(pthread_create(&_pThid, NULL, Thread::threadFun, this) != 0)
{
perror("pthread_create");
return;
}
_isRunning = true;//子线程已经运行
}
void Thread::join()
{
if(_isRunning == true)//子线程运行时才需要pthread_join()
{
pthread_join(_pThid, nullptr);
_isRunning = false;
}
}
Thread::Thread()
:_pThid(0)
,_isRunning(false)
{}
Thread::~Thread()
{
if(_isRunning)
{
pthread_detach(_pThid);//子线程退出时,资源由OS进行回收
}
}
void * Thread::threadFun(void* p)
{
Thread *pTh = (Thread *)p;
if(pTh != nullptr)
{
pTh -> run();//调用派生类重写过的虚函数
}
return NULL;
}
}
test.cc
#include "thread.hh"
#include "MutexLock.hh"
#include "Condition.hpp"
#include <unistd.h>
#include <iostream>
using namespace std;
using namespace my;
class Sellor
:public Thread
{
public:
Sellor(int &num, MutexLock &mutex, Condition &cond)
:_num(num)
,_mutex(mutex)
,_cond(cond)
{
start();
}
void run()
{
//....do something
int i = 0;
while(i<10)
{
_mutex.lock();
if(_num == 0)
{
_cond.wait();
if(_num == 0)//在收到唤醒信号和lock的期间,num被其它线程减到0了
{
_mutex.unlock();
continue;
}
}
_num--;
cout << "sell:1" << endl;
i++;
_mutex.unlock();
}
}
private:
int &_num;
MutexLock &_mutex;
Condition &_cond;
};
class Producer
:public Thread
{
public:
Producer(int &num, MutexLock &mutex, Condition &cond)
:_num(num)
,_mutex(mutex)
,_cond(cond)
{
start();
}
void run()
{
//....do something
int i = 0;
while(i < 10)
{
_mutex.lock();
_num++;
i++;
cout << "produce:1" << endl;
_cond.notify();
_mutex.unlock();
usleep(0.5);
}
}
private:
int &_num;
MutexLock &_mutex;
Condition &_cond;
};
void test()
{
MutexLock mutex;
Condition cond(mutex);
int num = 10;
Producer p(num, mutex, cond);
Sellor s(num, mutex, cond);
Producer p2(num, mutex, cond);
Sellor s1(num, mutex, cond);
Sellor s2(num, mutex, cond);
p.join();
s.join();
p2.join();
s1.join();
s2.join();
cout << num << endl;
}
int main()
{
test();
return 0;
}
更规范的写法是下面这种:
#ifndef __MY__CUSTOMER__H
#define __MY__CUSTOMER__H
#include "thread.hh"
#include "TaskQueue.hh"
#include <unistd.h>
#include <iostream>
using namespace std;
namespace my
{
class Customer
:public Thread
{
public:
Customer(TaskQueue & taskQue)
:_taskQue(taskQue){}
private:
void run()
{
//....do something
int i = 0;
while(i++ < 10)
{
int num = _taskQue.pop();
cout << "Customer:" << num << endl;
}
}
TaskQueue & _taskQue;
};
}
#endif
Prodeucer.hh
#ifndef __MY__PRODUCER__H
#define __MY__PRODUCER__H
#include "thread.hh"
#include "TaskQueue.hh"
#include <unistd.h>
#include <iostream>
using namespace std;
namespace my
{
class Producer
:public Thread
{
public:
Producer(TaskQueue & taskQue)
:_taskQue(taskQue){}
private:
void run()
{
//....do something
::srand(::clock());//调用C函数规范写法,函数名前加上::
int i = 0;
while(i++ < 10)
{
int num = ::rand()%100;
_taskQue.push(num);
cout << "Producer:" << num << endl;
usleep(0.5);
}
}
TaskQueue & _taskQue;
};
}
#endif
test.cc
#include "thread.hh"
#include "TaskQueue.hh"
#include "Customer.hh"
#include "Prodeucer.hh"
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <memory>
using namespace std;
using namespace my;
void test()
{
TaskQueue taskQue(5);
Producer p(taskQue);
Customer s(taskQue);
unique_ptr<Thread> p2(new Producer(taskQue));
unique_ptr<Thread> s2(new Customer(taskQue));
p.start();
s.start();
p2->start();
s2->start();
p.join();
s.join();
p2->join();
s2->join();
}
int main()
{
test();
return 0;
}