初始化信号量
cpp
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
pshared:0表⽰线程间共享,⾮零表⽰进程间共享
value:信号量初始值
摧毁信号量
cpp
int sem_destroy(sem_t *sem);
等待信号量
cpp
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem); //P()
发布信号量
cpp
功能:发布信号量,表⽰资源使⽤完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem); //V()
基于环形队列的生产者消费者模型
复习环形队列

初始的时候环形队列的head和tail指向的都是同一个位置,在上图中也就是下标为0的位置,当环形队列为满的时候指向head和tail指向的也是0,因此根据head == tail == 0无法判端队列是空还是满的,因此要一个计数器来统计其中的元素个数
对信号量进行封装
cpp
#pragma once
#include <iostream>
#include <semaphore.h>
namespace SemModlue
{
int DefaultSemNum = 1;
class Sem
{
public:
Sem(int sem_value = DefaultSemNum)
:_sem_value(sem_value)
{
sem_init(&_sem,0,_sem_value);
}
~Sem()
{
sem_destroy(&_sem);
}
void P()
{
int n = sem_wait(&_sem);
(void)n;
}
void V()
{
int n = sem_post(&_sem);
(void)n;
}
private:
sem_t _sem; //信号量
int _sem_value; //信号量个数
};
}
对环形队列进行封装
cpp
#pragma once
#include <iostream>
#include <vector>
#include <pthread.h>
#include <semaphore.h>
#include "Sem.hpp"
namespace RingBufferModule
{
using namespace SemModlue;
template <typename T>
class RingBuffer
{
public:
RingBuffer(int cap)
:_ring(cap)
,_cap(cap)
,_p_step(0)
,_c_step(0)
,_space_num(cap)
,_data_num(0)
{
pthread_mutex_init(&_p_mutex,nullptr);
pthread_mutex_init(&_c_mutex,nullptr);
}
~RingBuffer()
{
pthread_mutex_destroy(&_p_mutex);
pthread_mutex_destroy(&_c_mutex);
}
void Enqueue(const T&in)
{
_space_num.P();
pthread_mutex_lock(&_p_mutex);
_ring[_p_step] = in;
_p_step++;
_p_step %= _cap;
pthread_mutex_unlock(&_p_mutex);
_data_num.V();
}
void PopQueue(T *out)
{
_data_num.P();
pthread_mutex_lock(&_c_mutex);
*out = _ring[_c_step];
_c_step++;
_c_step %= _cap;
pthread_mutex_unlock(&_c_mutex);
_space_num.V();
}
private:
std::vector<T> _ring; //用vector来模拟环形队列
int _cap; //容量
int _p_step; //生产者当前位置
int _c_step; //消费者当前位置
pthread_mutex_t _p_mutex; //生产者互斥锁
pthread_mutex_t _c_mutex; //消费者互斥锁
Sem _space_num; //当前空闲位置数量
Sem _data_num; //当前数据个数
};
}
测试文件
cpp
#include <iostream>
#include <unistd.h>
#include "Thread.hpp"
#include "BlockQueue.hpp"
#include "RingBuffer.hpp"
using namespace RingBufferModule;
void *Productor(void *args)
{
RingBuffer<int> *ringbuffer = static_cast<RingBuffer<int> *>(args);
int data = 0;
while(true)
{
//sleep(1);
ringbuffer->Enqueue(data);
std::cout << "生产了一个数据:" << data << std::endl;
data++;
}
}
void *Consumer(void *args)
{
RingBuffer<int> *ringbuffer = static_cast<RingBuffer<int> *>(args);
int data = 0;
while(true)
{
sleep(1);
ringbuffer->PopQueue(&data);
std::cout << "消费了一个数据:" << data << std::endl;
}
}
int main()
{
RingBuffer<int> *ringbuffer=new RingBuffer<int>(5);
pthread_t p1,p2,v1,v2,v3;
pthread_create(&p1,nullptr,Productor,(void*)ringbuffer);
pthread_create(&p2,nullptr,Productor,(void*)ringbuffer);
pthread_create(&v1,nullptr,Consumer,(void*)ringbuffer);
pthread_create(&v2,nullptr,Consumer,(void*)ringbuffer);
pthread_create(&v3,nullptr,Consumer,(void*)ringbuffer);
pthread_join(p1,nullptr);
pthread_join(p2,nullptr);
pthread_join(v1,nullptr);
pthread_join(v2,nullptr);
pthread_join(v3,nullptr);
return 0;
}
运行结果
