1. 定义
一种同步原语,可以用它实现锁和条件变量
初始化:
#include <semaphore.h>
sem_t s;
sem_init(&s, 0, 1)
第二个参数表示信号量的指针,第二个参数0表示信号量是在同一个进程的多个线程共享的,第三个参数是信号量的初始值
sem_wait
int sem_wait(sem_t* s) {
1.信号量减1
2.若信号量为负则等待
}
sem_post
int sem_post(sem_t* s) {
1.信号量加1
2.若有线程等待信号量就唤醒其中一个
}
2. 用二值信号量实现锁
sem_t m;
sem_init(&m, 0, 1)
sem_wait(&m);
//执行业务代码
sem_post(&m)
3. 用信号量实现条件变量
4. 信号量解决生产者消费者问题
5. 读者写者锁
含义:一旦一个读者获得了一个锁,其他读者也可以获取这个锁,但是想要获取写锁就必须等到所有读者都结束。
实现关键:第一个读者获取写锁,最后一个读者释放死锁。
分析:可以完成功能,但是有一些缺陷:公平性不好 ,容易饿死写者;用了太多锁,性能不好。
6. 哲学家就餐问题
基本含义:
- 哲学家围着一个圆桌
- 哲学家一会思考,不需要餐叉,一会吃饭,需要餐叉
- 哲学家吃饭要左右手都拿到餐叉
计算机模拟
while(1) {
think();
getforks();
eat();
putforks();
}
关键问题:如何实现getforks()和putforks()保证没有死锁,没有哲学家饿死,并且并发度高?
解决办法:
核心:每个餐叉对应一个信号量;修改某个哲学家或者某些哲学家的取餐叉的顺序(先左手还是先右手)
void getforks() {
if (p == 4) {
sem_wait(forks[right(p)]);
sem_wait(forks[left(p)]);
}
else {
sem_wait(forks[left(p)]);
sem_wait(forks[right(p)]);
}
}
7. 信号量实现
用到锁和条件变量