单例模式封装pthread.h互斥锁与条件变量,实现生产者消费者小程序 C++
一.前言
我们知道,在pthread.h的头文件中,有互斥锁mutex与条件变量cond可以用来实现对公共资源的互斥访问。当在C++程序中,需要封装成类,同时我们又明白互斥锁与条件变量只能申请一个,所以这里就需要用单例模式进行实现。
二.代码
thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using std::cout;
using std::endl;
/*
因为互斥锁与条件变量都只能申请一个,所以这里需要用单例设计模式来设计互斥锁与条件变量
*/
class Mutex
{
public:
//...
static Mutex* getMutex();
void lock();
void unlock();
friend class Condition;
private:
Mutex(){}
~Mutex(){}
static Mutex* _pMutex;
pthread_mutex_t _mutex;
};
#if 1
class Condition
{
public:
static Condition* getCond();
void wait(Mutex*);
void notify();
void notifyall();
private:
Condition(){}
~Condition(){}
static Condition* _pCond;
pthread_cond_t _cond;
};
#endif
#endif
thread.cpp
#include "thread.h"
/******************Mutex*************************/
Mutex* Mutex::getMutex(){
if (_pMutex == NULL){
_pMutex = new Mutex();
_pMutex->_mutex = PTHREAD_MUTEX_INITIALIZER;
}else{
return _pMutex;
}
}
void Mutex::lock(){
pthread_mutex_lock(&_mutex);
}
void Mutex::unlock(){
pthread_mutex_unlock(&_mutex);
}
/******************Condition*************************/
#if 1
Condition* Condition::getCond(){
if (_pCond == NULL){
_pCond = new Condition();
_pCond->_cond = PTHREAD_COND_INITIALIZER;
}
else {
return _pCond;
}
}
void Condition::wait(Mutex* mutex){
pthread_cond_wait(&_cond, &mutex->_mutex);
}
void Condition::notify(){
pthread_cond_signal(&_cond);
}
void Condition::notifyall(){
pthread_cond_broadcast(&_cond);
}
#endif
main.cpp
#include "thread.h"
const int CONSUMER_SIZE = 3;
const int PRODUCER_SIZE = 1;
int tickets = 1000;
Mutex *Mutex::_pMutex = NULL;
Mutex *mutex = Mutex::getMutex();
Condition *Condition::_pCond = NULL;
Condition *cond = Condition::getCond();
void *consumerFunc(void *args)
{
int *id = (int *)args;
while (1)
{
mutex->lock();
while (tickets == 0)
{
cond->wait(mutex);
}
cout << *id << " cunsumer use one ticket, now there are " << --tickets << " left" << endl;
mutex->unlock();
}
pthread_exit(NULL);
}
void *producerFunc(void *args)
{
int *id = (int *)args;
while (1)
{
mutex->lock();
if (tickets == 0)
{
tickets += 100;
cout << "producer has produced " << tickets << " tickets" << endl;
//cond->notify();
cond->notifyall();
}
mutex->unlock();
}
pthread_exit(NULL);
}
int main()
{
int ret;
int consumer_id[CONSUMER_SIZE];
int producer_id[PRODUCER_SIZE];
pthread_t consumers[CONSUMER_SIZE], producers[PRODUCER_SIZE];
for (int i = 0; i < CONSUMER_SIZE; i++)
{
consumer_id[i] = i + 1;
ret = pthread_create(&consumers[i], NULL, consumerFunc, &consumer_id[i]);
if (ret)
{
cout << "pthread_create ERROR!" << endl;
}
}
for (int i = 0; i < PRODUCER_SIZE; i++)
{
producer_id[i] = i + 1;
ret = pthread_create(&producers[i], NULL, producerFunc, &producer_id[i]);
if (ret)
{
cout << "pthread_create ERROR!" << endl;
}
}
pthread_exit(NULL);
return 0;
}