背景:无论是软件方法与硬件方法都不能实现放权等待,需要有新的机制实现
信号量:跟变量差不多,可以直接用一个int就实现,也可以使用记录型信号量。通常用一个信号量表示系统中某个资源的数量。
一对原语wait,signal。传入信号量,决定这时候临界资源是否可进入,不进入就怎么怎么样。巴拉巴拉。因为原语,整个操作一气呵成,可以实现互斥。
wait signal通常称为P V操作
//记录型信号量
typedef struct {int value; //资源数struct process * L; //等待队列
} semaphore;void wait(semaphore s){s.value --;if (S.value < 0){block(s.l); //如果资源不够,调用阻塞原语,将其加入阻塞队列}
}void signal (semaphore s){s.value ++;if (S.value <= 0){wakeup(s.L); //释放资源之后,发现有别的进程需要使用调用wakeup原语}}
semaphore mutex = 1;
p1(){...P(mutex); //先P操作表示自己想用,如果临界资源不够就会将自己这个进程阻塞critical section;V(mutex); //V操作表示自己已经用完这个资源,如果有别的资源就会唤醒其他进程
}
p2(){...P(mutex);critical section;V(mutex);
}
semaphore s = 0;
p1(){代码xx;xxx;xx;V(s);xx;
}
p2(){xxP(s); //如果p2先运行到这里,执行P操作,此时信号量为0,就会将自己阻塞xxx; //那么就可以实现只有p1运行完V操作p2才能运行P操作之后代码xxx;
}
问题背景:有一个缓冲区,一个进程要写另外一个进程要读。
要点:
semaphore mutex = 1, full = 0, empty = 5;
//mutex表示互斥信号量,full表示当前缓冲区有0块数据,empty表示刚开始有5个大小空间
consumer(){while(1){P(full); //表示自己需要消耗一个数据P(mutex); //我需要访问缓冲区拿走;V(mutex); //我要释放缓冲区访问权限V(empty); //我拿走了一个数据,就有一个空间被释放出来}
}producer(){while(1){P(empty); //我要占用一个空位写入数据P(mutex);写数据;V(mutex);V(full); //}
}
问题:爸爸给女儿苹果吃,妈妈给儿子橘子吃,但妈妈爸爸用的是一个盘子。
要点:用上一个问题类似分析就可以得到
semaphore mutex = 1, empty = 5, orange = 0, apple = 0;
//mutex盘子互斥量,empty表示当前有5个盘子是空的,orange表示盘子当前有0个橘子,apple类似
father(){P(empty);P(mutex);放橘子;V(orange);
}
//妈妈类似,把orange改apple
daughter(){P(orange);P(mutex);吃橘子;V(empty);
}
问题:一个提供者,为三个吸烟者提供原材料,三个吸烟者需要用不同的东西抽烟。
要点:如何控制提供者为三个吸烟者提供原材料呢?
semaphore s1 = s2 = s3 = 0;
int turn = 0;
provider(){switch (turn):case 0:提供第一个原材料;V(s1);break;case 1:提供第二种原材料V(s2);break;case 2:提供第三种原材料;V(s3);break;turn = (turn + 1) % 3;
}smoker1(){p(s1);抽烟;
}
//其他类似
问题:允许多个读者可以同时对文件进行读操作。只允许一个写者文件对文件进行写。写文件时候不允许其他进程进行读或者写。写执行写之前保证其余读者和写者全部退出。
要点:
第一个方法:对读者进行计数,如果有计数,说明有进程在读,其他读者可以直接进行读文件,写文件直接阻塞就行。
semaphore rw = 1;
int count = 0;
semaphore mutex = 1;writer(){P(rw); //写文件表示我想写写文件;V(rw);
}reader(){P(mutex); //控制读文件互斥访问count变量if (count == 0) //如果当前是第一个读进程,跟写文件表示我想读P(rw);count ++;V(mutex);读文件;P(mutex);count --;if (count == 0);V(rw);V(mutex);
}
另外一个方法,在上一个方法之上再添加一个控制信号量,可以实现读写公平。分析可以发现确实可以读写公平,为什么不知道。
semaphore rw = 1;
int count = 0;
semaphore mutex = 1;
semaphore w = 1; //添加的信号量writer(){P(w);P(rw); //写文件表示我想写写文件;V(rw);P(w);
}reader(){P(w);P(mutex); //控制读文件互斥访问count变量if (count == 0) //如果当前是第一个读进程,跟写文件表示我想读P(rw);count ++;V(mutex);V(w);读文件;P(mutex);count --;if (count == 0);V(rw);V(mutex);
}
问题:有n个哲学家,但是只有n-1双筷子。哲学家坐在圆桌旁边,左右手各放一个筷子。只有拿起左右两边的筷子才能吃饭。
此问题涉及死锁,可以先看死锁在看这个问题。
解决办法
上一篇: 新概念英语的学习方法总结