皮特森算法 软互斥 怎么不会导致饥饿了?我怎么看都觉得会饥饿啊

2016-03-06 21:09:16 +08:00
 yangyaofei

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,所以不就饥饿了么?
求解答

4123 次点击
所在节点    程序员
8 条回复
ppdg
2016-03-06 22:11:10 +08:00
flag[1] = false;了 P0 还死循环个毛啊
yangyaofei
2016-03-07 08:25:38 +08:00
@ppdg 但是 turn 是 0 啊,怎么不是死循环……
zado
2016-03-07 08:36:40 +08:00
即使 turn 是 0 也一样会跳出循环,&& 就是必须同时满足两边的条件才死循环。
zado
2016-03-07 08:42:38 +08:00
哦,如果你说的是 P0 的话,那 turn 是 0 的话早直接就能跳出循环了,不管 flag[1] 是什么。
soundofu
2016-03-07 09:23:33 +08:00
试试将 int turn; 声明为 volatile int turn; ?
hxndg
2016-03-07 09:54:35 +08:00
俄,我个人理解哈:并不会饥饿阿,虽然计算机确实是在轮询,但是 p0 的阻塞条件除了 turn 之外,是由 p1 控制的,而 p1 会在进入阻塞之前释放掉对 flag[0]和 turn 的控制。换言之,两者都会在进入阻塞之前释放掉控制的信号量
yangyaofei
2016-03-07 10:55:15 +08:00
@ppdg
@hxndg
@soundofu
@zado
啊啊啊啊,脑残了, while 那个地方看错了Σ(゚Д゚)Σ(゚Д゚)Σ(゚Д゚)Σ(゚Д゚)Σ(゚Д゚)
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 也会被马上再次调度并获得锁,然后继续运行后面的代码。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/261533

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX