过桥问题:
A,B地之间有一座每次只能过一辆车的桥,假如桥上正在过的是A到B的车,B到A的车必须等待所有A到B的车过完才能上桥,反之亦然。
第一步
由于第一辆车能够上桥之后,后续的车不需要再验证是否能上桥,轮到了就能上。
semaphore mutex = 1; //桥的使用权信号量
int A2B = 0, B2A = 0; //A到B,或者B到A的车等待数量
//A to B
A2B++;
if (A2B == 1) {
wait (mutex);
}
//过桥
A2B--;
if (A2B == 0) { //假如A到B的最后一辆车过完,释放桥
signal(mutex);
}
第二步
由于A2B,B2A也是共享资源,因此也需要信号量保护
semaphore mutex = 1; //桥的使用权信号量
int A2B = 0, B2A = 0; //A到B,或者B到A的车等待数量
semaphore A_mutex = 1, B_mutex = 1;
//A to B
wait(A_mutex);
A2B++;
signal(A_mutex);
if (A2B == 1) {
wait (mutex);
}
//过桥
wait(A_mutex);
A2B--;
signal(A_mutex);
if (A2B == 0) { //假如A到B的最后一辆车过完,释放桥
signal(mutex);
}
第三步
显然,if 验证语句只验证第一辆车,导致假如第二辆或者之后的车进来之后,直接就会过桥。这是错误的。
方法:将A_mutex 范围变大
semaphore mutex = 1; //桥的使用权信号量
int A2B = 0, B2A = 0; //A到B,或者B到A的车等待数量
semaphore A_mutex = 1, B_mutex = 1;
//A to B
wait(A_mutex);
A2B++;
if (A2B == 1) {
wait (mutex);
}
signal(A_mutex); //等待车上桥之后,才允许进入等待,因此也避免了后续车跳过if直接上桥
//过桥
wait(A_mutex);
A2B--;
if (A2B == 0) { //假如A到B的最后一辆车过完,释放桥
signal(mutex);
}
signal(A_mutex);
B到A的代码类似,此处不再赘述