介绍
初始化
#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 操作要在互斥锁的加,解锁操作之前,否则可能产生死锁
- 若生产者无限制,只需一个信号量