Linux--生产者与消费者模型-- 信号量实现

31 篇文章 0 订阅

信号量

  • 本质:计数器+pcb等待队列;
  • 作用:实现进程或线程间的同步与互斥;
  • P操作:计数-1;判断计数<0 ,则阻塞进程或线程(将其加入pcb等待队列)
  • V操作:计数+1;唤醒pcb等待队列上的一个进程或线程;
  • 同步的实现:通过计数器对资源进行计数;获取资源前进程P操作,合理则获取,不合理则阻塞。产生一个资源,则进行一次V操作。
  • 互斥的实现:计数最大为1,表示只有一个资源,访问前P操作,访问完进行V操作;

操作接口

  • 定义信号量:sem_t sem;
  • 初始化信号量
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    · sem:信号量变量;
    · pshared:0-线程间 / !0-进程间;
    · value:初值;
    · 返回值:成功返回0,失败返回-1;
  • P操作:
    int sem_wait(sem_t *sem);
    int sem_trywait(sem_t *sem);
    int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
  • V操作:
    int sem_post(sem_t *sem);
  • 销毁信号量:
    int sem_destroy(sem_t *sem);

信号量与条件变量的区别与联系

  • 都是用于实现同步
  • 条件变量的使用中条件是否满足需要我们自己判断,信号量不需要;
  • 条件变量的使用需要搭配互斥锁;信号量不需要

使用信号量实现生产者与消费者模型

class RingQueue{
	std::vector<int> _arr;
	int _capacity;
	int _step_read;
	int _step_write;
	sem_t _sem_lock;//用于实现互斥的信号量
	sem_t _sem_idle;//对于生产者-空闲节点是资源
	sem_t _sem_data;//对于消费者-数据节点是资源
};
#include <cstdio>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

class RingQueue{
    private:
        std::vector<int> _arry;
        int _capacity;
        int _step_read;
        int _step_write;
        sem_t _sem_lock;//用于实现互斥的信号量
        sem_t _sem_idle;//对于生产者-空闲节点是资源
        sem_t _sem_data;//对于消费者-数据节点是资源
    public:
        RingQueue(int cap=5):_capacity(cap), _arry(cap), 
        _step_read(0), _step_write(0) {
            //sem_init(信号量,标志-0线程-1进程, 初值)
            sem_init(&_sem_lock, 0, 1);
            sem_init(&_sem_idle, 0, cap);
            sem_init(&_sem_data, 0, 0);
        }
        ~RingQueue() {
            sem_destroy(&_sem_data);
            sem_destroy(&_sem_idle);
            sem_destroy(&_sem_lock);
        }
        bool Push(int data) {
            sem_wait(&_sem_idle);//判断有没有空闲节点
            sem_wait(&_sem_lock);//加锁
            _arry[_step_write] = data;
            _step_write = (_step_write + 1)%_capacity;
            sem_post(&_sem_lock);//解锁
            sem_post(&_sem_data);//数据节点+1唤醒消费者
            return true;
        }
        bool Pop(int *data) {
            sem_wait(&_sem_data);//数据节点数-1,判断是否合理
            sem_wait(&_sem_lock);//加锁
            *data = _arry[_step_read];
            _step_read = (_step_read + 1)%_capacity;
            sem_post(&_sem_lock);//解锁
            sem_post(&_sem_idle);//空闲节点数+1唤醒生产者
            return true;
        }
};

void *productor(void *arg)
{
    RingQueue *q = (RingQueue*)arg;
    int i = 0;
    while(1){
        q->Push(i);
        printf("生产者入队数据:%d\n", i++);
    }
    return NULL;
}
void *customer(void *arg)
{
    RingQueue *q = (RingQueue*)arg;
    while(1) {
        int data;
        q->Pop(&data);
        printf("消费者出队数据: %d\n", data);
    }
    return NULL;
}
int main (int argc, char *argv[])
{
    RingQueue q;
    pthread_t ptid[4], ctid[4];
    int ret;
    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&ptid[i], NULL, productor, &q);
        if (ret != 0) {
            printf("create thread error\n");
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&ctid[i], NULL, customer, &q);
        if (ret != 0) {
            printf("create thread error\n");
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        pthread_join(ptid[i], NULL);
        pthread_join(ctid[i], NULL);
    }
    return 0;
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值