posix semaphore 生产消费情况测试

版权声明: https://blog.csdn.net/dashoumeixi/article/details/84668720

有名信号量:  文件在 /dev/shm

单消费单生产 的情况. 把sem_open 改为 sem_init 就是基于内存的信号量

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <pthread.h>
#define  NBUFF 10
#define  SEM_MUTEX "/semmutex"
#define  SEM_NSTORED "/semnstored"
#define  SEM_NEMPTY "/semnempty"

int nitems;
struct {
    int buf[NBUFF];
    sem_t *mutex,*nstored,*nempty;  //mutex 在这个例子没必要.只是为了扩展起见
}share;
static void * producer(void * p)
{
    for(int i = 0 ; i < nitems; ++i){
        sem_wait(share.nempty);
        sem_wait(share.mutex);
        share.buf[i%NBUFF] = i;
        sem_post(share.mutex);
        sem_post(share.nstored);
    }

    return 0;
}
static void * consumer(void * p)
{
    for(int i =0 ; i < nitems;++i){
        sem_wait(share.nstored);
        sem_wait(share.mutex);
        printf("consumer : %d\n" , share.buf[i]);
        sem_post(share.mutex);
        sem_post(share.nempty);
    }
    return 0;
}


int main(int agrc, char**argv)
{

    if( agrc < 2){
        puts("nitems?");
        return 0;
    }
    nitems = atoi(argv[1]);
    int flag = O_CREAT;
    mode_t  mode = 0644;
    share.mutex = sem_open(SEM_MUTEX,flag,mode,1);
    
    // 消费者 一开始初始化 0
    share.nstored = sem_open(SEM_NSTORED,flag,mode,0);

    // 生产一开始初始化可连续进入 NBUFF次
    share.nempty = sem_open(SEM_NEMPTY,flag,mode,NBUFF);
    pthread_t  tid_p , tid_c;
    pthread_create(&tid_p,NULL,producer,NULL);
    pthread_create(&tid_c,NULL,consumer,NULL);

    pthread_join(tid_p,NULL);
    pthread_join(tid_c,NULL);
    int emptyvalue  , storevalue ;
    sem_getvalue(share.nempty,&emptyvalue);
    sem_getvalue(share.nstored,&storevalue);
    printf("nempty:%d, nstored:%d\n" , emptyvalue,storevalue);


    return 0;
}

多个生产者 单个消费:

需要注意的是多个生产者线程 退出时 还需要通知其他的生产者线程退出,否则将死锁. 

比如在下面例子中 总共生产20个数据. 启动50个消费者线程. 则只有20个线程能正常退出,其他30个线程将一直等待;

又或者你能确定只有一个生产者,但这样又失去了多生产者的意义了

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <pthread.h>
#define  NBUFF 10
#define  MAXTHREADS 50


int nitems , nproducers;
struct {
    int buf[NBUFF];
    sem_t mutex,nstored,nempty;
    int nindex; //用于记录生产者生产到哪
}share;
static void * producer(void * p)
{
   int i = 0;
   while(1){
        sem_wait(&share.nempty);
        sem_wait(&share.mutex);
        if(share.nindex >= nitems){    //生产完成,线程退出

            //注意!! 多个生产线程,要让剩余的线程退出.否则死锁
            sem_post(&share.mutex);    
            sem_post(&share.nempty);  //如果不知道为什么,可以注释这行看看情况
            break;
        }
        share.buf[i%NBUFF] = i++;
        share.nindex++;
        sem_post(&share.mutex);
        sem_post(&share.nstored);
    }

    return 0;
}
static void * consumer(void * p)
{
    for(int i =0 ; i < nitems;++i){
        sem_wait(&share.nstored);
        sem_wait(&share.mutex);
        printf("index:%d , consumer : %d\n" , i,share.buf[i%NBUFF]);
        sem_post(&share.mutex);
        sem_post(&share.nempty);
    }
    return 0;
}


int main(int agrc, char**argv)
{

    if( agrc < 2){
        puts("nitems producers");
        return 0;
    }
    nitems = atoi(argv[1]);
    nproducers = atoi(argv[2]) ;
    if(nproducers > MAXTHREADS)
        nproducers = MAXTHREADS;
    int flag = O_CREAT;
    mode_t  mode = 0644;
    sem_init(&share.mutex,0,1);
    sem_init(&share.nempty,0,NBUFF);
    sem_init(&share.nstored,0,0);

    pthread_t  tid_p[MAXTHREADS] , tid_c;
    for(int i = 0; i < nproducers ; ++i)
        pthread_create(tid_p+i,NULL,producer,NULL);

    pthread_create(&tid_c,NULL,consumer,NULL);

    for(int i =  0 ; i< nproducers; ++i)
        pthread_join(tid_p[i],NULL);

    pthread_join(tid_c,NULL);
    int emptyvalue  , storevalue ;
    sem_getvalue(&share.nempty,&emptyvalue);
    sem_getvalue(&share.nstored,&storevalue);
    printf("nempty:%d, nstored:%d\n" , emptyvalue,storevalue);

    return 0;
}

多生产多消费:

需要注意的是:

1.在生产者线程退出时要通知一下消费者线程,否则消费者将一直等待,无法退出线程

2.在消费者中还需要添加自行退出线程的代码, 就像多生产者一样, 否则消费者线程将无法全部退出,

除非你能确定,消费者只有一个 或者 生产者的数量一定大于消费者 ,但这样的消费者代码不好,有太多的限制了;

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <pthread.h>
#define  NBUFF 10
#define  MAXTHREADS 50


int nitems , nproducers , nconsumers;
struct {
    int buf[NBUFF];
    sem_t mutex,nstored,nempty;
    int index_producer;
    int index_consumer;
}share;
static void * producer(void * p)
{
   int i = 0;
   while(1){
        sem_wait(&share.nempty);
        sem_wait(&share.mutex);
        if(share.index_producer >= nitems){
            sem_post(&share.mutex);
            sem_post(&share.nempty);
            
            /*
                需要注意.一定要通知消费者,否则消费者死锁
                比如5个线程全部生产完毕. 此时消费并不知道.还在sem_wait等待
            */
            sem_post(&share.nstored);    
            break;
        }
        share.buf[i%NBUFF] = i++;
        share.index_producer++;
        sem_post(&share.mutex);
        sem_post(&share.nstored);
    }

    return 0;
}
static void * consumer(void * p)
{
    while(1){
        sem_wait(&share.nstored);
        sem_wait(&share.mutex);


        if(share.index_consumer >= nitems){  //多消费者的情况,需要判断是否已经完成消费
            
            /*
                当生产者通知结束后.由于当前是多消费者的情况.
                所以必须加上这2行代码,除非你能确定, 只有一个消费者或者
                生产者一定是大于消费者的
            */
            sem_post(&share.nstored);    //自行退出线程
            sem_post(&share.mutex);
            break;
        }
        printf("index:%d , consumer : %d\n" , share.index_consumer,
               share.buf[share.index_consumer%NBUFF]);
        share.index_consumer++;
        sem_post(&share.mutex);
        sem_post(&share.nempty);
    }
    return 0;
}


int main(int agrc, char**argv)
{

    if( agrc < 3){
        puts("nitems producers consumers");
        return 0;
    }
    nitems = atoi(argv[1]);
    nproducers = atoi(argv[2]) ;
    nconsumers = atoi(argv[3]);

    if(nproducers > MAXTHREADS)
        nproducers = MAXTHREADS;
    if(nconsumers > MAXTHREADS)
        nconsumers = MAXTHREADS;

    int flag = O_CREAT;
    mode_t  mode = 0644;
    sem_init(&share.mutex,0,1);
    sem_init(&share.nempty,0,NBUFF);
    sem_init(&share.nstored,0,0);

    pthread_t  tid_p[MAXTHREADS] , tid_c[MAXTHREADS];
    for(int i = 0; i < nproducers ; ++i)
        pthread_create(tid_p+i,NULL,producer,NULL);

    for(int i = 0; i < nconsumers ; ++i)
        pthread_create(tid_c+i,NULL,consumer,NULL);

    for(int i =  0 ; i< nproducers; ++i)
        pthread_join(tid_p[i],NULL);
    for(int i =0 ; i < nconsumers ; ++i)
        pthread_join(tid_c[i],NULL);

    int emptyvalue  , storevalue ;
    sem_getvalue(&share.nempty,&emptyvalue);
    sem_getvalue(&share.nstored,&storevalue);
    printf("nempty:%d, nstored:%d\n" , emptyvalue,storevalue);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/dashoumeixi/article/details/84668720
今日推荐