用条件变量(Condition Variable)实现信号量(Semaphore)

来源:互联网 发布:人工智能培训就业班 编辑:程序博客网 时间:2024/06/05 16:24

用条件变量(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;
}