对于信号量的问题,我们具体应该如何处理
常见共五类问题,1.生产者-消费者问题,2.理发师问题,3.读者写者问题,4.哲学家就餐问题
5.单纯的同步问题
1.生产者-消费者问题
六个步骤:
1.判断存在几类进程--每个进程对应一个函数
2.在每个函数内部,使用中文来描述动作(观察是否循环):是一次性动作,还是循环动作
3.分析每一个动作之前,是否需要P什么,只要有P,那么必然存在V,这里还需要对于缓冲区的互斥访问:而且对于缓冲区的PV操作一定要紧贴访问代码
4.PV操作全部写完,随后确定信号量的值
5.检查多个P连续出现的地方,是否会导致死锁:如果发生死锁,那么我们就尝试交换P操作的位置,观察是否还会造成死锁
6.检查是否满足题目要求
定义信号量 semaphore
2.理发师问题
理发师和顾客之间并没有生产和消费关系,而是服务-被服务的关系
int waiting = 0;//正在等待的顾客数量
semaphore mutex = 1; //对于wait的互斥访问
semaphore service = 0; //为了避免顾客没有等待过程,直接进入被服务的代码,需要将这个服务设置为0
semaphore customer = 0; //当顾客到店的话,唤醒服务人员,而没有顾客,服务人员就等待
customer_i(){
P(mutex);
if(waiting>=MAX){V(mutex); return;} //如果店内的顾客过多,直接离开,并且需要把锁打开
取号;
++waiting;
V(mutex);
V(customer);
P(service);//等待被叫号
被服务;
}
server_j(){
while(1){
P(mutex);
if(waiting>0){
叫号;
--waiting;
V(mutex);
V(service);
提供服务;
} else{
V(mutex);
P(customer); //如果没有顾客,就等待
} //else end
} //while end
}
note:顾客是没有循环的,被服务结束就会离开,但是服务人员是循环的,一直提供服务
3.读者写者问题
同类进程不互斥,异类进程互斥
4.哲学家就餐问题
关键在于解除死锁
三种思路:
1. 限制并行(该思路不通用,不建议使用)
单号哲学家先拿左手边筷子,双号哲学家先拿右手边筷子,破坏了请求并保持,这个左右手是哲学家面向桌子的左右手
2.限制并发进程数量(解法2通用,但是并发度不高,不建议使用)
同一时刻仅允许一个哲学家在进行就餐,禁止并行,串行化
3.让进程一口气获得所有资源,然后再开始运行(通用且并发度高)
定义一个mutex确保所有资源是一口气拿下的,拿资源之前先P(mutex),拿完资源之后V(mutex)
如果使用信号量来表示资源,同样存在并发度不高的可能,因为如果获取不到资源就会将进程阻塞
我们改用资源数量(用一个int型的变量来表示资源)
注意:资源数量的定义是使用int类型,而LOCK是semaphore
process(){
while(1){
P(LOCK);
if(资源数量足够){
获取所有资源;
对应资源数量减少;
V(LOCK);
break;
}
V(LOCK);
}
进程执行;
P(LOCK);
资源释放;
V(LOCK);
}
5.单纯的同步问题
这种问题就是画一个前驱后继图就可以了