linux编程:通过信号量实现生产者与消费者模型
信号量: 用于实现同步与互斥。
本质: 就是一个计数器,对资源进行计数以及提供一个pcb等待队列,向外提供P/V操作接口,实现同步与互斥
P操作: 在临界资源访问之前进行P操作,计数-1,对计数进行判断,小于0则不符合访问条件,使线程阻塞或报错返回,否则正确返回获取资源
V操作: 在生产资源之后,进行V操作,计数+1,唤醒一个等待的线程或进程
互斥的实现:
计数为1,表示资源只有一个,在资源访问之前P操作–加锁,其他线程则无法访问(这时候表示已经没有资源了),访问完毕之后进行V操作–解锁流程:
- 创建信号量;
- 初始化信号量;
- 在获取资源之前P操作;
- 生产资源之后V操作;
- 销毁信号量
#include<vector>
#include<pthread.h>
#include<semaphore.h>
#include<cstdio>
#define MAX_QUEUE 5
class RingQueue{
private:
std::vector<int>_queue;
int _read_step;
int _write_step;
int _capacity;
sem_t _sem_lock;//用于实现锁
sem_t _sem_idle;//用于统计空闲空间数
sem_t _sem_data;//用于统计数据空间
public:
RingQueue(int cap = MAX_QUEUE):_queue(cap),_capacity(cap),_read_step(0),_write_step(0){
sem_init(&_sem_lock,0,1);//用于实现锁则计数为1
sem_init(&_sem_idle,0,cap);//空闲空间初始为5
sem_init(&_sem_data,0,0);//数据初值为0
}
~RingQueue(){
sem_destroy(&_sem_lock);
sem_destroy(&_sem_idle);
sem_destroy(&_sem_data);
}
bool Push(int data){
sem_wait(&_sem_idle);//判断是否有空闲空间,空闲空间计数-1
sem_wait(&_sem_lock);//P操作加锁
_queue[_write_step]=data;
_write_step=(_write_step+1)%_capacity;
sem_post(&_sem_lock);//V操作解锁
sem_post(&_sem_data);//数据空间计数+1
return true;
}
bool Pop(int *data){
sem_wait(&_sem_data);//判断是否有数据空间,数据空间计数-1
sem_wait(&_sem_lock);//P操作加锁
*data=_queue[_read_step];
_read_step=(_read_step+1)%_capacity;
sem_post(&_sem_lock);//V操作解锁
sem_post(&_sem_idle);//空闲空间计数+1
return true;
}
};
void *thr_cus(void *arg){
RingQueue *queue = (RingQueue*)arg;
while(1){
int data;
queue->Pop(&data);
printf("get data:%d --\n",data);
}
return NULL;
}
void *thr_pro(void *arg){
RingQueue *queue = (RingQueue*)arg;
int data= 0;
while(1){
queue->Push(data);
printf("get data:%d ++\n",data++);
}
return NULL;
}
int main()
{
int ret,i;
RingQueue queue;
pthread_t ctid[4],ptid[4];
for(i=0;i<4;i++){
ret=pthread_create(&ctid[i],NULL,thr_cus,(void*)&queue);
if(ret!=0){
printf("craete theread error\n");
return -1;
}
}
for(i=0;i<4;i++){
ret=pthread_create(&ptid[i],NULL,thr_pro,(void*)&queue);
if(ret!=0){
printf("craete theread error\n");
return -1;
}
}
for(i=0;i<4;i++){
pthread_join(ctid[i],NULL);
pthread_join(ptid[i],NULL);
}
}
运行结果