信号量
- 信号量初始化时为n,也就是说可以指定任意值
-一 个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步 - 既可以用于线程同步又可以用于进程同步
主要应用函数:
sem_init函数
sem_destroy函数
sem_wait函数
sem_trywait函数
sem_timedwait函数
sem_post函数
以上6 个函数的返回值都是:成功返回0, 失败返回-1,同时设置errno。
sem_t类型,本质仍是结构体。sem_t sem; 规定信号量sem不能 < 0。头文件 <semaphore.h>
1、sem_init函数
- 初始化一个信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
- 参1:sem信号量
- 参2:pshared取0用于线程间;取非0(一般为1)用于进程间
- 参3:value指定信号量初值
- 信号量的初值,决定了占用信号量的线程的个数
2、sem_destroy函数
- 销毁一个信号量
int sem_destroy(sem_t *sem);
3、sem_wait函数
- 给信号量加锁 ,对信号量进行–操作
int sem_wait(sem_t *sem);
- 信号量大于0,则信号量,类比 (pthread_mutex_lock))
- 信号量等于0,造成线程阻塞
4、sem_post函数
- 给信号量解锁 ,对信号量进行++
int sem_post(sem_t *sem);
- 将信号量++,同时唤醒阻塞在信号量上的线程 (类比pthread_mutex_unlock)
生产者和消费者模型
/*信号量实现 生产者 消费者问题*/
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#define NUM 5
//全局数组实现环形队列
int queue[NUM];
//空格子信号量, 产品信号量
sem_t blank_number, product_number;
void *producer(void *arg)
{
int i = 0;
while (1) {
//生产者将空格子数--,为0则阻塞等待
sem_wait(&blank_number);
//生产一个产品
queue[i] = rand() % 1000 + 1;
printf("----Produce---%d\n", queue[i]);
//将产品数++
sem_post(&product_number);
//借助下标实现环形
i = (i+1) % NUM;
sleep(rand()%3);
}
}
void *consumer(void *arg)
{
int i = 0;
while (1) {
//消费者将产品数--,为0则阻塞等待
sem_wait(&product_number);
printf("-Consume---%d\n", queue[i]);
//消费一个产品
queue[i] = 0;
//消费掉以后,将空格子数++
sem_post(&blank_number);
i = (i+1) % NUM;
sleep(rand()%3);
}
}
int main(int argc, char *argv[])
{
pthread_t pid, cid;
sem_init(&blank_number, 0, NUM); //初始化空格子信号量为5
sem_init(&product_number, 0, 0); //产品数为0
//创建2个线程,一个生产者,一个消费者
pthread_create(&pid, NULL, producer, NULL);
pthread_create(&cid, NULL, consumer, NULL);
//回收子线程
pthread_join(pid, NULL);
pthread_join(cid, NULL);
//销毁信号量
sem_destroy(&blank_number);
sem_destroy(&product_number);
return 0;
}
输出:
结论:
- 从前往后消费