Linux编程–信号量

1、相关函数

#include <semaphore.h>
// 初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
// 加锁信号量
int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
// 解除信号量
int sem_post(sem_t *sem);

2、信号量示例实现生产者&消费者模型

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

#define NUM 5    // 定义最大信号量
// 定义数据模型
struct object{
    int num;
};
// 生产消息数据结构
struct object* queue[NUM];
// 1、定义2个信号量(生产&消费)
sem_t consumer, producer;
// 消息者函数主体
void *consume(void *arg){
    int i = 0;
    while(1){
        // 消费者应该等待生产者的信号量释放,没有生产就没有消费
        sem_wait(&producer);
        // 消费掉一个量
        struct object *obj = queue[i];
        printf("consumer ----- %d |", obj->num);
        queue[i] = NULL;
        // 打印当前还剩下的待消费量
        int j = i+1;
        struct object *p = queue[j%NUM];
        while(p){
            printf(" %d", p->num);
            p = queue[++j%NUM];
        }
        putchar('\n');
        // 增加一个消费量
        sem_post(&consumer);
        usleep(rand()%500000);
        free(obj);
        i = ++i % NUM;
    }
}
// 生产者函数主体
void *production(void *arg){
    int i = 0;
    while(1){
        // 等待消费信号量(消费信号量初始为5)
        sem_wait(&consumer);
        // 有需求才生产
        struct object *obj = malloc(sizeof(struct object));
        obj->num = rand() & 99;
        // 生产出来的产品循环挂到队列中
        queue[i] = obj;
        printf("producer ----- %d\n", obj->num);
        // 增加一个生产量
        sem_post(&producer);
        usleep(rand()%500000);
        i = ++i % NUM;
    }
}
int main(){
    // 产生一个随机数种子
    srand(time(NULL));
    // 初始化两个信号量
    sem_init(&consumer, 0, NUM);
    sem_init(&producer, 0, 0);

    // 初始化2个线程,分别模拟生产与消费
    pthread_t tid_c, tid_p;
    pthread_create(&tid_c, NULL, consume, NULL);
    pthread_create(&tid_p, NULL, production, NULL);

    // 主线程合并(回收)两个子线程
    pthread_join(tid_c, NULL);
    pthread_join(tid_p, NULL);

    // 信号量使用后及时释放销毁
    sem_destroy(&consumer);
    sem_destroy(&producer);

    return 0;
}

执行结果:

parallels@ubuntu:~/Linux/sem$ ./sem.out
producer ----- 98
consumer ----- 98 |
producer ----- 34
producer ----- 1
consumer ----- 34 | 1
consumer ----- 1 |
producer ----- 98
producer ----- 2
consumer ----- 98 | 2
consumer ----- 2 |
producer ----- 35
consumer ----- 35 |
producer ----- 0
producer ----- 96
consumer ----- 0 | 96
producer ----- 98
consumer ----- 96 | 98
producer ----- 35
producer ----- 1
consumer ----- 98 | 35 1
producer ----- 99
producer ----- 1
producer ----- 3
consumer ----- 35 | 1 99 1 3
consumer ----- 1 | 99 1 3
consumer ----- 99 | 1 3
producer ----- 32
consumer ----- 1 | 3 32
producer ----- 65
consumer ----- 3 | 32 65
producer ----- 0
producer ----- 3
consumer ----- 32 | 65 0 3
producer ----- 96
consumer ----- 65 | 0 3 96
producer ----- 98
producer ----- 96
consumer ----- 0 | 3 96 98 96
consumer ----- 3 | 96 98 96
producer ----- 97
consumer ----- 96 | 98 96 97
consumer ----- 98 | 96 97
consumer ----- 96 | 97
consumer ----- 97 |
producer ----- 0
consumer ----- 0 |
producer ----- 66
consumer ----- 66 |
producer ----- 35
producer ----- 65
producer ----- 97
consumer ----- 35 | 65 97
^C
parallels@ubuntu:~/Linux/sem$

Leave a Reply