多线程的判断条件语句

多线程 while 和 if 判断条件的区别

让我们看一个这样一种情况:

class WaitPerson implements Runnable {
  private Restaurant restaurant;
  public WaitPerson(Restaurant r) { restaurant = r; }
  public void run() {
    try {
      while(!Thread.interrupted()) {
        synchronized(this) {
          while(restaurant.meal == null)
            wait(); // ... for the chef to produce a meal
        }
        print("Waitperson got " + restaurant.meal);
        synchronized(restaurant.chef) {
          restaurant.meal = null;
          restaurant.chef.notifyAll(); // Ready for another
        }
      }
    } catch(InterruptedException e) {
      print("WaitPerson interrupted");
    }
  }
}

其中,while(restaurant.meal == null) 中使用了 while。可以换成 if 吗?

        不行。原因是,在 synchronized 这个同步块中,当任务进入到 同步块语句中先进行一次条件的判断。如果不符合,线程进入 wait()状态。这里注意 wait() 和 sleep() 的区别,调用 wait() 会释放该对象的锁,并将线程挂起。而 sleep() 则不释放锁,只是将线程挂起。当锁释放后,下一个任务进入该锁中,此时如果它改变 restaurant.meal 的值(即改变先前的判断条件),然后再调用 notifyAll() 。调用 notifyAll() 将唤醒此时该锁中被挂起的线程,当它从这个锁中离开后,之前那个 wait()状态的线程将可能重新进入这个对象的锁中,此时,如果没有 while判断,它在 wait()之后将直接执行下面的流程,而不必再次判断条件是否符合。而实际上上一个任务中已经将判断条件改变了,被唤醒的任务不应该直接往下执行,而应该重新判断条件是否符合。所以此时必须用 while。

        你必须用一个检查感兴趣的条件的 while循环包围 wait()。这样做的本质就是检查所感兴趣的特定条件,如果在不满足的条件下返回到 wait()中。惯用的方法就是使用 while来编写这种代码。如果你使用 if 则无法应付下面的情况:

可能有多个任务在等待相同一个锁,而第一个唤醒的任务可能会改变这种状态(即使你没有这么做,有人会通过继承你的类去这么做)。如果属于这种情况,那么这个任务应当被再次挂起,直至其感兴趣的条件发生变化。

在这个任务从 wait()被唤醒的时刻,有可能会有某个地方的任务已经做出了改变,从而使这个任务在此刻不能执行,或者执行其操作已经显得无关紧要。此时,应该通过再次调用 wait()来将其重新挂起。

也有可能某些任务出于不同的原因在等待你的对象上的锁(在这种情况下,你必须使用 notifyAll() )。在这种情况下,你需要检查是否已经由正确的原因唤醒,如果不是,就再次调用 wait()。

 

转载于:https://my.oschina.net/lemos/blog/832378

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值