用條件變量(Condition Variable)實現信號量(Semaphore)


用條件變量(Condition Variable)實現信號量(Semaphore),

主要是通過條件變量控制資源數的加減操作,在這里定義sem_t 為

    struct sem{
        int num;
        pthread_mutex_t lock;
        pthread_cond_t  cond;   
           
    };

資源數由num決定,當num為0時應用條件變量讓線程掛起,直到條件滿足之后再次獲取資源。

void  sem_init(sem_t * semm, int num) 初始化函數,定義資源數。

 

void sem_wait(sem_t * semm) 獲取資源,獲得資源后,資源數-1,未獲得資源則掛起等待,

這里需要注意的一點是,pthread_cond_wait在掛起等待的時候是不會占用互斥鎖(mutex),

進而能保證sem_post對num的操作不被掛起。

 

void sem_post(sem_t * semm) 釋放資源,資源數+1;

代碼如下:

//"semaphore_xx.h"

#ifndef SEMAPHORE_XX_20121008
#define SEMAPHORE_XX_20121008

#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

namespace sem_xx{
    struct sem{
        int num;
        pthread_mutex_t lock;
        pthread_cond_t  cond;   
           
    };

    typedef struct sem sem_t;

    void  sem_init(sem_t * semm, int num){
        semm->num = num;
        pthread_mutex_init(&(semm->lock), NULL);
        pthread_cond_init(&(semm->cond), NULL); 
    }

    void sem_wait(sem_t * semm){
        pthread_mutex_lock(&(semm->lock));
        while ( semm->num == 0)
          pthread_cond_wait(&(semm->cond), &(semm->lock));
        semm->num--;     
        pthread_mutex_unlock(&(semm->lock));
    }


    void sem_post(sem_t * semm){
        pthread_mutex_lock(&(semm->lock));
        /*fuck! Here is a stupid mistake!Just add the num will be ok!!
          Otherwise,we will be blocked here!
        while ( semm->num == 0)
          pthread_cond_wait(&(semm->cond), &(semm->lock));
         
        */
        semm->num++;     
        pthread_mutex_unlock(&(semm->lock));
       
        pthread_cond_signal(&(semm->cond));
    }
}
#endif

 

利用上面代碼實現生產者-消費者模式:

代碼如下:

//"test.cpp"

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <semaphore.h>
#include "semaphore_xx.h"

#define NUM 5
int queue[NUM];

using namespace sem_xx;

sem blank_number, product_number;

void *producer(void *arg) 
{
  int p = 0;
  while (1) {
    sem_wait(&blank_number);
    queue[p] = rand() % 1000 + 1;
    printf("Produce %d\n", queue[p]);
    sem_post(&product_number);
    p = (p+1)%NUM;
    sleep(rand()%5);
  }
}
 
void *consumer(void *arg) 
{
  int c = 0;
  while (1) {
    sem_wait(&product_number);
    printf("Consume %d\n", queue[c]);
    queue[c] = 0;
    sem_post(&blank_number);
    c = (c+1)%NUM;
    sleep(rand()%5);
  }
}
 
int main(int argc, char *argv[]) 
{
  pthread_t pid, cid;  
  sem_init(&blank_number, NUM);
  sem_init(&product_number, 0);

 
  pthread_create(&pid, NULL, producer, NULL);
  pthread_create(&cid, NULL, consumer, NULL);
  pthread_join(pid, NULL);
  pthread_join(cid, NULL);

 
  return 0;
}  

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com