持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
经典的进程同步问题
生产者消费者问题:
1.利用信号量解决生产者消费者 例题
int in=0,out=0;
item buffer[n];
semaphore mutex=1,empty=n,full=0;
void 生产者(){
do{
生成一个产品;
......
wait(empty);
wait(muter);
//写进缓冲区
buffer[in]=产品
in=(in+1)%n;
singal(mutex);
singal(full)
}while(true)
}
void 消费者(){
do{
wait(full);
wait(muter);
//写进缓冲区
产品=buffer[out]
out=(out+1)%n;
singal(mutex);
singal(empty)
消费产品
}while(true)
}
分析:我们先按照要求定义变量。生产者消费者对于缓冲区访问是互斥的,所以我们定义mutex=1;必须要生产放进去缓冲区,消费者才能消费,所以两个是同步关系。首先,我们拿到一个空资源,然后互斥访问缓冲区,把产品放进去,然后用full+1,表示写进去一个资源。消费者,先判断有没有商品,然后再互斥访问缓冲区,最后消费了把empty+1。
2.利用add信号量解决
定义变量和之前一样的
void 生产者(){
do{
生成一个产品;
......
Swait(empty,mutex)//括号里面两个资源都需要满足
//写进缓冲区
buffer[in]=产品
in=(in+1)%n;
Ssingal(mutex,full)
}while(true)
}
消费者同理修改
分析:在获取资源时候,我们必须把需要资源全部获取了才能继续下去
3.利用管程解决
分析:首先需要定义一个管程,命名pc,他包括两个过程,put(x)和get(x),分别对应生产者消费者。当count>=n表示缓冲池满了,生产者必须等待,count=0,表示缓冲池是空;消费者必须等待
对于条件变量notfull,notemploy有两个过程cwait和csingal
Monitor producerconsumerP{
item buffer[N];
condition notfull,noteempoty;
int count;
public:
void put(item x){
if(count>=N) cwait(notfull);
buffer[in]=x;
in=(in+1)%n;
count++;
csignal(notemploy)
}
void get(item x){
if(count<=0) cwait(notempty)
x=buffer[out];
out=(out+1)%N;
count--;
csignal(notfull);
}
{in=0;out=0;count=0}
}PC
void 生产者(){
item x;
while(true){
...
生产
pc.put(x)
}
void (){消费者
item x;
while(true){
...
pc.get(x)
消费
}
}
读者写者问题:
例题:来帮小朋友们解决一个问题吧:幼儿园大班和小班之间有一条刚好一人宽的过道,阿姨规定同一个方向的小朋友可以连续通过过道,当某一个方向有小朋友通过的时候,另一方向的小朋友必须乖乖排队等待;当对方没有小朋友走过道的时候,另一方向的小朋友就可以通过了。请大哥哥大姐姐们用记录型型号量帮小朋友们解决一些这个问题吧,用算法写出大班小朋友和对面小班小朋友应该遵守的代码。
semaphore wait = 1; // 互斥信号量,表示过道的数量
int count1 = 0; // 大班小朋友在过道上的人数
semaphore mutex1 = 1; // 大班小朋友的互斥信号量,保证count1操作的完整执行
int count2 = 0; // 小班小朋友在过道上的人数
semaphore mutex2 = 1; // 小班小朋友的互斥信号量,保证count2操作的完整执行
P大() {
P(mutex1);
count1++;
if(count1 == 1) // 大班第一个小朋友通过
P(wait);
V(mutex1);
{通过过道};
P(mutex1);
count1--;
if(count1 == 0) //大班最后一个小朋友通过,释放过道
V(wait);
V(mutex1);
}
P小() {
P(mutex2);
count2++;
if(count2 == 1) // 小班第一个小朋友通过
P(wait);
V(mutex2);
{通过过道};
P(mutex2);
count2--;
if(count2 == 0) // 小班最后一个小朋友通过,释放过道
V(wait);
V(mutex2);
}
分析:这题属于读者写者问题,不同大小的朋友表示一类。我们先看过道是不是为空,是空可以上人,在上过道互斥pv,当下过道,也是同样pv。
哲学家就餐问题
有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。
约束条件
(1)只有拿到两只筷子时,哲学家才能吃饭。
(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。
(3)任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子。
筷子是临界资源,一段时间只允许一位哲学家使用。为了表示互斥,用一个信号量表示一只筷子,五个信号量构成信号量数组。。算法描述如下:n用五支筷子的信号量构成信号量数组:
Semaphore chopstick[5]={1,1,1,1,1};
p(stick[i]);
p(stick[(i+1) % 5]);
进餐;
v(stick[i]);
v(stick[(i+1) % 5]);
思考;
当哲学家饥饿时,总是先去拿他左边的筷子,执行wait(chopstick[I]),成功后,再去拿他右边的筷子,执行wait(chopstick[I+1]%5);成功后便可进餐。进餐毕,先放下他左边的筷子,然后再放下右边的筷子。当五个哲学家同时去取他左边的筷子,每人拿到一只筷子且不释放,即五个哲学家只得无限等待下去,引起死锁 可以采取信号量集的方法。swait,ssingal