信号量

Posted on 2023-02-24 13:56  lyc2002  阅读(33)  评论(0编辑  收藏  举报

介绍

初始化

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

功能:初始化信号量

参数:

  • sem:信号量变量地址
  • pshared:0,线程同步;非 0,进程同步
  • value:初始化信号量初始资源数

返回值:

  • 成功返回 0
  • 失败返回 -1,error 指示错误号

销毁

#include <semaphore.h>

int sem_destroy(sem_t *sem);

功能:销毁信号量

参数:

  • sem:信号量变量地址

返回值:

  • 成功返回 0
  • 失败返回 -1,error 指示错误号

申请资源

#include <semaphore.h>

int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

功能:申请资源

  • 当线程调用这个函数,并且 sem 中的资源数 >0,线程不会阻塞,资源数 -1
  • 当 sem 中的资源数 ==0,线程阻塞;但 trywait 不会被阻塞,直接返回 -1

参数:

  • sem:信号量变量地址

返回值:

  • 成功返回 0
  • 失败返回 -1,error 指示错误号

提供资源

#include <semaphore.h>

int sem_post(sem_t *sem);

功能:提供资源

参数:

  • sem:信号量变量地址

返回值:

  • 成功返回 0
  • 失败返回 -1,error 指示错误号

获得资源数

#include <semaphore.h>

int sem_getvalue(sem_t *sem, int *sval);

功能:查看 sem 中拥有的资源个数

参数:

  • sem:信号量变量地址
  • sval:传出参数,资源个数会被写到该指针对应的内存处

返回值:

  • 成功返回 0
  • 失败返回 -1,error 指示错误号

简单使用

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

#define N 30

pthread_mutex_t mutex;
sem_t full, empty;

int buf[N], idx = -1;

void * producer(void *arg)
{
    while (1) {
        sem_wait(&empty);
        pthread_mutex_lock(&mutex);
        buf[++idx] = 1;
        printf("producer offer %d\n", idx);
        sem_post(&full);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    
    pthread_exit(NULL);
}

void * consumer(void *arg)
{
    while (1) {
        sem_wait(&full);
        pthread_mutex_lock(&mutex);
        printf("consumer get %d\n", idx);
        buf[idx--] = 0;
        sem_post(&empty);
        pthread_mutex_unlock(&mutex);
        sleep(3);
    }
    
    pthread_exit(NULL);
}

int main()
{
    pthread_mutex_init(&mutex, NULL);
    sem_init(&full, 0, 0);
    sem_init(&empty, 0, N);
    
    pthread_t t1[5], t2[5];
    for (int i = 0; i < 5; i++) {
        pthread_create(&t1[i], NULL, producer, NULL);
        pthread_create(&t2[i], NULL, consumer, NULL);
    }
    for (int i = 0; i < 5; i++) {
        pthread_join(t1[i], NULL);
        pthread_join(t2[i], NULL);
    }
    
    pthread_mutex_destroy(&mutex);
    sem_destroy(&full);
    sem_destroy(&empty);
    
    return 0;
}

注意事项

  • 信号量的 P,V 操作要在互斥锁的加,解锁操作之前,否则可能产生死锁
  • 若生产者无限制,只需一个信号量