PV操作的相关练习题

1.PV信号量的分类

1) 普通型信号量

wait(S) {

// P(S)

while(S <= 0);

S = S - 1;

}

signal(S) {

// V(S)

S = S + 1;

}

没有实现让权等待!让进程处于忙等状态!

2) 记录型信号量

void wait(S) {

//一定要注意:先改变value,然后再去做block或者wakeup操作

S.value--;

if(S.value < 0) {

/不带等号,说明减之前S.value = 0,没有资源了/

add this process to S.L;

block(S.L);

}

void signal(S) {

//一定要注意:先改变value,然后再去做block或者wakeup操作

S.value++;

if(S.value <= 0) {

		/*加之前S.value 最大为-1,反正是个负数,说明需要将它wakeup*/
		remove this process from S.L;
		wakeup(S.L);
	}	
}

//记录型信号量实现了让权等待!

2.经典模型

1)前驱图

-->进程的同步,前一个结点释放后V,后面的结点去P。

semaphore a1, a2, b1, b2, c, d, e = 0;

Process S1() {
    ....;
    v(a1);
    V(a2);
}

Process S2() {
	P(a1);
    ....;
    V(b1);
}

....
    
Process S6() {
	P(d);
    p(e);
    ....;
}

2)生产者消费者问题

  • 单生产者单消费者问题

/*设缓冲区大小为n*/
semaphore empty = n;  //记录空闲缓冲区数量
semaphore full = 0;	  //记录
semaphore mutex = 1;  //实现互斥访问缓冲区

producer() {
    while(true) {
        //P(mutex) // false,这样申请可能会导致死锁!
        produce a product;
        P(empty);	//获取空闲缓冲区资源
        P(mutex);	//进入临界区 --- 互斥加紧
        add the item to the buffer;
        V(mutex);
        V(full);
    }
}


consumer() {
	while(true) {
        P(full);
        P(mutex);
        pull an item from the buffer;
        V(mutex);
        V(empty);
        consume the product;
    }
}
  • 多生产者多消费者问题

semaphore mutex = 1; //用于实现盘子的互斥访问
semaphore apple = 0; //用于实现爸爸和儿子的同步
semaphore orange = 0;//用于实现母亲和女儿的同步

dad() {
	while(true) {
		prepare an apple;
        P(mutex);
        put the apple on the plate;
        V(apple);  //此处不能释放mutex,dad放苹果和儿子取苹果应该是一个连续的过程!****
    }
}

son() {
	while(true) {
	P(apple);
        pull the apple from the plate;
        V(mutex);
        eat the apple;
    }	
}

mom() {
	while(true) {
	prepare an orange;
        P(mutex);
        put the orange on the plate;
        V(orange);  //此处不能释放mutex,dad放苹果和儿子取苹果应该是一个连续的过程!****
    }
}

daughter() {
	while(true) {
		P(orange);
        pull the orange from the plate;
        V(mutex);
        eat the orange;
    }	
}
  • 吸烟者问题

/*与爸爸妈妈儿子那个问题有区别,三个吸烟者各求所需,如果不是自己需要的原料,就不会去取,所以不需要互斥信号量,只需要同步信号量*/

semaphore offer1 = 0;
semaphore offer2 = 0;
semaphore offer3 = 0;
semaphore finish = 0;   //用来判断原料是否被使用

producer() {
    while(true) {
		int num = random() % 3;  //产生0到2的随机数
        if(num == 0) {
            V(offer1);
        }else if(num == 1) {
            V(offer2);
        }else {
			V(offer3);
        }
        P(finish);
    }
}

smoker_i() {
	while(true) {
		P(offeri);
        抽烟i;
        V(finish);
    }
}

3)读者写者问题

/*没有实现读写公平*/
int cnt = 0;  //记录读者的数量
semaphore rw = 1;  //用于实现读写互斥
semaphore mutex = 1;  //用于更新cnt时的互斥

writer() {
    while(true) {
		P(rw);
        write();
        V(rw);
    }
}

reader() {
    while(true) {
		P(mutex);
        if(cnt == 0) {
            /*第一个读的人*/
            P(rw);
        }
        cnt++;
        V(mutex);
        read();
        P(mutex);
        cnt--;
        if(cnt == 0) {
            /*最后一个读的人*/
            V(rw);
        }
        V(mutex);
    }
}
/*上面的算法没有实现读写公平,写操作很容易产生饥饿*/
semaphore w = 1;  //用于实现写优先; 
semaphore rw = 1;
semaphore mutex = 1;
int cnt = 0;

writer() {
	while(true) {
		P(w);
        P(rw);
        write();
        V(rw);
        V(w);
    }
}


reader() {
	while(true) {
        P(w);
        P(mutex);
        if(cnt == 0) {
			P(rw);
        }
        cnt++;
        V(mutex);
        V(w);   //在这里释放w,后面不再需要w
        read();
        P(mutex);
        cnt--;
        if(cnt == 0) {
            /*最后一个读的人*/
            V(rw);
        }
        V(mutex);
    }
}

4)哲学家就餐问题

/*进餐取筷子时置mutex,其他人不能动,取完筷子其他人就可以动了*/
semaphore mutex = 1;
semaphore chopstick[5] = {1, 1, 1, 1, 1};

Pi() {
	while(true) {
        P(mutex);
        P(chopstick[i]);
        P(chopstick[(i+1)%5]);
        V(mutex);
        eat;
        V(chopstick[i]);
        V(chopstick[(i+1)%5]);
        think;
    }
}

3.王道后面的练习题

semaphore mutex = 1; //互斥访问临界区
semaphore empty = N;
semaphore odd = 0;
semaphore even = 0;

P1() {
    while(true) {
        n = produce();
        P(empty);
        P(mutex);
        put(n);
        if(n % 2 == 0) {
			V(even);
        } else {
            V(odd);
        }
        V(mutex);
    }
}

P2() {
	while(true) {
        P(odd);
        P(mutex);
        getOdd();
        V(mutex);
        V(empty);
        countOdd();
    }
}

...

int i = 0, int j = 0;  //取号为i,叫号为j
semaphore mutex_i = 1, mutex_j = 1;

consumer(){
    while(true){
        进入面包店;
        P(mutex_i);
        取号i;
        i++;
        V(mutex_i);
        等待被叫买面包后离开;
    }
}


seller() {
    while(true) {
		P(mutex_j);
        if(i > j) {
            叫号j;
            j++;
            V(mutex_j);
            买面包;
        }else{
            V(mutex_j);
            休息;
        }
    }
}

semaphore vat = 1;   //互斥使用水缸;
semaphore well = 1;  //互斥使用水井;
semaphore pail = 3;  //水桶有3个
semaphore empty = 10;
semaphore full = 0;

smallmonk() {
	while(){
		P(empty);
        P(pail);
        P(well);
        打水;
        V(well);
        P(vat);
        将水倒入水缸;
        V(vat);
        V(pail);
        V(full);
    }
}

bigmonk() {
	while(true) {
        P(full);
        P(pail);
        P(vat);
        从水缸中取水;
        V(vat);
        V(empty);
        喝水;
        V(pail);
       
    }
}

semaphore Sa = n, Sb = n; //超过n时才会暂停,所以此处应该包含n
semaphore emptya = m, emptyb = m;
semaphore fulla = 0, fullb = 0;
semaphore mutex = 1; //互斥的访问一个仓库

StoreA(){
	while(true) {
		P(emptya);
		P(Sa);
		P(mutex);
		生产一个A并放入仓库;
		V(mutex);
		V(Sb);  //***
		V(fulla);
	}
}

StoreB(){
	while(true) {
		P(emptyb);
		P(Sb);
		P(mutex);
		生产一个B并放入仓库;
		V(mutex);
		V(Sa);  //***
		V(fullb);
	}
}


Composition() {
	while(true) {
		P(fulla);
		P(fullb);
		P(mutex);
		取出一个A和一个B,组装;
		V(mutex);
		V(emptya);
		V(emptyb);
	}
}

semaphore barber = 0; //用来实现同步
semaphore costomer = 0; //用来实现同步
int count = 0;
semaphore mutex = 1; //实现互斥访问count

Barber() {
	while(true) {
		P(costomer); //有没有顾客,没有就睡觉;
		P(mutex);
		count--;
		V(mutex);
		理发;
		V(barber);
	}
}



Costomer() {
	while(true) {
		P(mutex);
		if(count < n) {
			count++;
			V(costomer);  //叫barber
			P(barber);
			V(mutex);
			理发;
		}else {
			V(mutex);
			离开;
		}
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子味的晚霞和少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值