Makefile
cpp
复制代码
ConProd:ConProd.cc
gcc -o ConProd ConProd.cc -std=c++11 -lstdc++ -pthread
.PHONY:clean
clean:
rm -f ConProd
lockGuard.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <pthread.h>
class Mutex
{
public:
Mutex(pthread_mutex_t *pmtx)
: _pmtx(pmtx)
{
}
void *lock()
{
pthread_mutex_lock(_pmtx);
}
void unlock()
{
pthread_mutex_unlock(_pmtx);
}
~Mutex()
{
}
// private:
pthread_mutex_t *_pmtx;
};
class lockGuard
{
public:
lockGuard(pthread_mutex_t *pmtx)
: _mtx(pmtx)
{
_mtx.lock();
}
~lockGuard()
{
_mtx.unlock();
}
private:
Mutex _mtx;
};
Task.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <functional>
class Task
{
typedef std::function<int(int, int)> func_t;
public:
Task()
{
}
Task(int x, int y, func_t func)
: _x(x), _y(y), _func(func)
{
}
int operator()()
{
return _func(_x, _y);
}
// private:
int _x;
int _y;
func_t _func;
};
BlockQueue.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
#include <unistd.h>
#include "lockGuard.hpp"
const int gDefaultCap = 5;
template <class T>
class BlockQueue
{
public:
BlockQueue(int capacity = gDefaultCap)
: _capacity(capacity)
{
pthread_mutex_init(&_mtx, nullptr);
pthread_cond_init(&_Empty, nullptr);
pthread_cond_init(&_Full, nullptr);
}
bool Empty()
{
return _bq.empty();
}
bool Full()
{
return _bq.size() == _capacity;
}
void push(const T &in)
{
lockGuard lock(&_mtx);
while (Full())
{
pthread_cond_wait(&_Full, &_mtx);
}
_bq.push(in);
sleep(1);
pthread_cond_signal(&_Empty);
}
void pop(T *out)
{
lockGuard lock(&_mtx);
while (Empty())
{
pthread_cond_wait(&_Empty, &_mtx);
}
*out = _bq.front();
_bq.pop();
pthread_cond_signal(&_Full);
}
~BlockQueue()
{
pthread_mutex_destroy(&_mtx);
pthread_cond_destroy(&_Empty);
pthread_cond_destroy(&_Full);
}
private:
std::queue<T> _bq; // 阻塞队列
int _capacity; // 容量上限
pthread_mutex_t _mtx; // 通过互斥锁保证队列安全
pthread_cond_t _Empty; // 用它来表示bq是否为空的条件
pthread_cond_t _Full; // 用它来表示bq是否为满的条件
};
cpp
复制代码
#include "BlockQueue.hpp"
#include "Task.hpp"
#include <pthread.h>
#include <unistd.h>
#include <time.h>
int Add(int x, int y)
{
return x + y;
}
void *consumer(void *args)
{
BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;
Task task;
while (true)
{
bqueue->pop(&task);
std::cout << pthread_self() << " : " << task._x << " + " << task._y << "=" << task() << std::endl;
}
return nullptr;
}
void *productor(void *args)
{
BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;
while (true)
{
// int x, y;
// std::cout << "Please Enter x:";
// std::cin >> x;
// std::cout << "Please Enter y:";
// std::cin >> y;
int x = rand() % 1000 + 1;
usleep(rand() % 1000);
int y = rand() % 1500 + 1;
Task task(x, y, Add);
bqueue->push(task);
std::cout << pthread_self() << " : " << x << " + " << y << " =?" << std::endl;
sleep(1);
}
return nullptr;
}
int main()
{
srand((unsigned int)time(nullptr));
BlockQueue<Task> *bqueue = new BlockQueue<Task>(10);
pthread_t c[3], p[3];
for (int i = 0; i < 3; i++)
{
pthread_create(c + i, nullptr, consumer, bqueue);
}
for (int i = 0; i < 3; i++)
{
pthread_create(p + i, nullptr, productor, bqueue);
}
for (int i = 0; i < 3; i++)
{
pthread_join(c[i], nullptr);
}
for (int i = 0; i < 3; i++)
{
pthread_join(p[i], nullptr);
}
delete bqueue;
return 0;
}