[Linux] - based semaphore producer consumer model

signal

In front of our producer-consumer model is based on blocking queue semaphore producer consumer model, it can be said that today we look at is based on circular queue.

POSIX semaphores

POSIX semaphores and the same effect SystemV semaphores are used for synchronization, to achieve conflict-free access to shared resources purposes. But POSIX can be used for inter-thread synchronization

Semaphore initialization

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
		pshared:0表示线程间共享,非零表示进程间共享
		value:信号量初始值

Destroy Semaphore

int sem_destroy(sem_t *sem);

Waiting for the semaphore

功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);

Released semaphore

功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem);

Circular queue-based producer consumer model

  • Circular queue array using simulation, to simulate the cyclic operation mode with characteristics
  • The ring structure of the start and end states are the same, is empty or not is determined is full, it may be determined by adding the full or the empty flag or a counter. Further it may reserve an empty position, as a full state
  • But we now have the semaphore counter this, it is a simple process synchronization between multiple threads
  • Simple sum it up is that you can not over me, I can not put you set a circle , here you are a consumer, I am a producer

Source Display

  • ring.hpp
#ifndef __RING_HPP__
#define __RING_HPP__

#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

#define NUM 32

using namespace std;

class Ring{
    private:
        int circle[NUM];//环形队列
        int cap;//信号量的容量
        int c_step;//消费者下标
        int p_step;//生产者下标
        sem_t sem_data;//消费者可以消费的数据
        sem_t sem_blank;//生产者可以生产的位置

        void P(sem_t &s)
        {
            sem_wait(&s);
        }
        void V(sem_t &s)
        {
            sem_post(&s);
        }
    public:
        Ring():cap(NUM)
        {
            c_step = p_step = 0;
            sem_init(&sem_data,0,0);
            sem_init(&sem_blank,0,NUM);
        }

        //消费者调用该接口进行消费
        void GetData(int& out)
        {
            P(sem_data);//消费者申请数据资源消费
            out = circle[c_step];//消费者从环形队列中取数据
            c_step++;
            V(sem_blank);//消费者增加空间
            c_step %= cap;//当走到最后时重新置为0
        }
        //生产者调用该接口进行生产
        void PutData(const int& in)
        {
            P(sem_blank);//生产者申请空间生产
            circle[p_step] = in;//往环形队列中插入数据
            p_step++;//下标++
            V(sem_data);//生产者增加数据
            p_step %= cap;//因为是环形队列,当走到下标最后时将它重置为0
        }

        ~Ring()
        {
            sem_destroy(&sem_data);
            sem_destroy(&sem_blank);
        }
};

#endif
#include "ring.hpp"
#include <time.h>

void* consumer(void* arg)
{
    Ring* r = (Ring*)arg;
    int data;
    for(;;){
        r->GetData(data);
        cout << "consumer data:"<< data <<endl;
    }
}

void* producter(void* arg)
{
    Ring* r = (Ring*)arg;
    for(;;){
        int data = rand() % 100 + 1;
        r->PutData(data);
        cout << "product data:"<< data <<endl;
        sleep(1);
    }
}

int main()
{
    srand((unsigned long)time(NULL));//生成随机数
    Ring r;//定义一个环形队列,基于信号量
    pthread_t c,p;//创建两个线程c为消费者,p为生产者
    pthread_create(&c,NULL,consumer,(void*)&r);//让生产者和消费者都看到该环形队列
    pthread_create(&p,NULL,producter,(void*)&r);


    pthread_join(c,NULL);
    pthread_join(p,NULL);

    return 0;
}
  • Makefile
ring:ring.cc
	g++ -o $@ $^ -lpthread
.PHONY:clean
clean:
	rm -f ring
Published 167 original articles · won praise 175 · views 10000 +

Guess you like

Origin blog.csdn.net/chenxiyuehh/article/details/97539310