V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yangyaofei
V2EX  ›  程序员

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

  •  
  •   yangyaofei ·
    yangyaofei · 2016-03-06 21:09:16 +08:00 · 4130 次点击
    这是一个创建于 3188 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    8 条回复    2016-03-07 11:20:36 +08:00
    ppdg
        1
    ppdg  
       2016-03-06 22:11:10 +08:00
    flag[1] = false;了 P0 还死循环个毛啊
    yangyaofei
        2
    yangyaofei  
    OP
       2016-03-07 08:25:38 +08:00 via Android
    @ppdg 但是 turn 是 0 啊,怎么不是死循环……
    zado
        3
    zado  
       2016-03-07 08:36:40 +08:00
    即使 turn 是 0 也一样会跳出循环,&& 就是必须同时满足两边的条件才死循环。
    zado
        4
    zado  
       2016-03-07 08:42:38 +08:00
    哦,如果你说的是 P0 的话,那 turn 是 0 的话早直接就能跳出循环了,不管 flag[1] 是什么。
    soundofu
        5
    soundofu  
       2016-03-07 09:23:33 +08:00
    试试将 int turn; 声明为 volatile int turn; ?
    hxndg
        6
    hxndg  
       2016-03-07 09:54:35 +08:00
    俄,我个人理解哈:并不会饥饿阿,虽然计算机确实是在轮询,但是 p0 的阻塞条件除了 turn 之外,是由 p1 控制的,而 p1 会在进入阻塞之前释放掉对 flag[0]和 turn 的控制。换言之,两者都会在进入阻塞之前释放掉控制的信号量
    yangyaofei
        7
    yangyaofei  
    OP
       2016-03-07 10:55:15 +08:00 via Android
    @ppdg
    @hxndg
    @soundofu
    @zado
    啊啊啊啊,脑残了, while 那个地方看错了Σ(゚Д゚)Σ(゚Д゚)Σ(゚Д゚)Σ(゚Д゚)Σ(゚Д゚)
    bp0
        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 也会被马上再次调度并获得锁,然后继续运行后面的代码。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3370 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:40 · PVG 19:40 · LAX 03:40 · JFK 06:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.