1:生产者消费者问题
生产者和消费者共享一个初始值为0,大小为n的缓冲区。
当缓冲区未满时,生产者才能生产产品。
当缓冲区未空时,消费者才能消费产品。
缓冲区属于临界资源,生产者和消费者需要互斥的访问。
semaphore mutex=1 //互斥信号量,生产者和消费者互斥访问缓冲区
semaphore empty=n //同步信号量,表示空缓冲区的数量
semaphore full=0 //同步信号量,表示产品数量即非空缓冲区的数量
producer ( ){
while(1){
生产产品
p(empty); //申请空缓冲区
p(mutex); //申请缓冲区的访问
放入空缓冲区
v(mutex); //取消对缓冲区的访问
v(full); // 增加一个产品,即增加一个非空缓冲区
}
}
consumer( ){
while(1){
p(full); //申请非空缓冲区
p(mutex); //申请缓冲区的访问
从缓冲区取出
v(mutex); //取消对缓冲区的访问
v(empty); //增加一个空缓冲区
消费产品
}
}
注意:对p(empty)/p(full)和p(mutex)的顺序不可以调换,如果调换会产生死锁。
- 如果此时缓冲区为满,如果生产者进程申请了对缓冲区的访问,而此时没有空缓冲区,生产者进程将会阻塞,而消费者进程无法进入缓冲区,消费者进程也会阻塞。
- 如果此时缓冲区为空,如果消费者进程申请了对缓冲区的访问,而此时没有非空缓冲区,消费者进程将会阻塞,而生产者进程无法进入缓冲区,生产者进程也会阻塞。
注意:生产者生产产品,消费者消费产品的代码不能放到缓冲区访问期间,会降低程序的并发度
2: 多生产者多消费者问题
semaphore plant=0 //同步信号量,表示盘子还可以放几个水果
semaohore apple=0 //同步信号量,表示盘子中苹果的数量
semaphore orange=0 //同步信号量,表示盘子中橘子的数量
dad( ){
准备苹果
p(plant);
放入苹果
v(apple);
}
mom( ){
准备橘子
p(plant);
放入橘子
v(orange);
}
daughter( ){
p(apple);
取走苹果
v(plant);
吃苹果
}
son( ){
p(orange);
取走橘子
v(plant);
吃橘子
}
注意:此时不需要设置对盘子的互斥访问量 semaphore mutex=1,因为此时apple orange plant 三个同步信号量的值最多有一个为1。在任何时刻只能由一个进程的p操作不会被阻塞,并进去临界区。
桌上有一空盘,只允许存放一个水果。爸爸可向盘中放苹果,也可向盘中放桔子。儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘中空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发进程的同步。
semaphore plant=1 //同步信号量,表示盘子可存放水果的数量
semaphore apple=0 //同步信号量,表示盘子中苹果的数量
semaphore orange=0 //同步信号量,表示盘子中橘子的数量
dad( ){
准备水果
p(plant);
放水果
if(苹果){
v(apple);
}else{
v(orange);
}
}
daughter( ){
p(apple);
拿走苹果
v(plant);
吃苹果
}
son( ){
p(orange);
拿走橘子
v(plant);
吃橘子
}
3:哲学家问题
semaphore chopstick[5]{1,1,1,1,1} //表示五只筷子 从0-4编号
semaphore mutex=1 //哲学家之间 互斥取筷子
pi( ){
while(1){
p(mutex);
p(chopstick[i]);//左边筷子
p(chopstick[(i+1)%5])//右边筷子
v(mutex);
吃饭
v(chopstick[i]);//左边筷子
v(chopstick[(i+1)%5])//右边筷子
思考
}
}
- 设置mutex互斥信号量,哲学家之间互斥的取筷子
- 最多允许四位哲学家取筷子
- 奇数的哲学家先拿左边筷子,再拿右边筷子,而偶数哲学家相反
4:读写者问题
默认读者优先:
semaphore rw=1 //对文件的互斥访问
int count =0 //记录当前读进程的个数
semaphore mutex=1 //保证对count变量的互斥访问
writer( ){
p(rw);
写文件
v(rw);
}
reader( ){
while(1){
p(mutex);
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 //保证对count变量的互斥访问
semaphore w=1 //读写公平
writer( ){
p(w);
p(rw);
写文件
v(rw);
v(w);
}
reader( ){
while(1){
p(w);
p(mutex);
if(count==0){
p(rw);
}
count++;
v(mutex);
v(w);
读文件
p(mutex);
count--;
if(count==0){
v(rw);
}
v(mutex);
}
}