wiki:https://zh.wikipedia.org/zh-cn/Peterson%E7%AE%97%E6%B3%95
最近做题,遇到这个
//flag[] is boolean array; and turn is an integer
flag[0] = false;
flag[1] = false;
int turn;
P0:
flag[0] = true;
turn = 1;
while (flag[1] == true && turn == 1)
{
// busy wait
}
// critical section
...
// end of critical section
flag[0] = false;
P1:
flag[1] = true;
turn = 0;
while (flag[0] == true && turn == 0)
{
// busy wait
}
// critical section
...
// end of critical section
flag[1] = false;
如上代码, P1 执行完了的时候 turn=0,P0 可能在 while 处死循环,肯定无法设置 turn=1,所以不就饥饿了么?
求解答
1
ppdg 2016-03-06 22:11:10 +08:00
flag[1] = false;了 P0 还死循环个毛啊
|
2
yangyaofei OP @ppdg 但是 turn 是 0 啊,怎么不是死循环……
|
3
zado 2016-03-07 08:36:40 +08:00
即使 turn 是 0 也一样会跳出循环,&& 就是必须同时满足两边的条件才死循环。
|
4
zado 2016-03-07 08:42:38 +08:00
哦,如果你说的是 P0 的话,那 turn 是 0 的话早直接就能跳出循环了,不管 flag[1] 是什么。
|
5
soundofu 2016-03-07 09:23:33 +08:00
试试将 int turn; 声明为 volatile int turn; ?
|
6
hxndg 2016-03-07 09:54:35 +08:00
俄,我个人理解哈:并不会饥饿阿,虽然计算机确实是在轮询,但是 p0 的阻塞条件除了 turn 之外,是由 p1 控制的,而 p1 会在进入阻塞之前释放掉对 flag[0]和 turn 的控制。换言之,两者都会在进入阻塞之前释放掉控制的信号量
|
7
yangyaofei OP |
8
bp0 2016-03-07 11:20:36 +08:00
不会死锁,只不过延迟一段时间而已。
如果 P1 执行完 turn = 0 后马上被 P0 抢占,那么 P0 会在 while 中等待。这时只有等 P0 的时间片用完以后, P1 才会被调度。 P1 被调度后继续往下运行,此时 turn 已经在 P0 中设置成 1 。所以 P1 不会在 while 处等待,而是继续运行后面的代码,当 P1 运行完成后会释放 flag[1],这样等 P0 再次被调度后,就能继续运行了。 如果使用真正的锁, P0 在 while 时就会进入睡眠并释放 CPU ,而 P1 会马上运行。当 P1 完成工作并解锁后, P0 也会被马上再次调度并获得锁,然后继续运行后面的代码。 |