为什么在多线程上下文中等待while循环条件是安全的?

时间:2015-05-21 18:22:23

标签: java multithreading

我很难真正理解,这是如何运作的:

while(<some condition>){
    wait();
}
OR this example:
while(<some condition>){
    condition.await();
}

当线程已经通过<some condition>时, 它可能真的发生了,<some condition>执行falsewait()await()已经wait()

因此,await()function playToFive() { console.log('Let\'s play Rock Paper Scissors'); var playerWins = 0; var computerWins = 0; while (playerWins === 5 || computerWins === 5) { if (humanVsMachine === 'player') { playerWins += 1; } else if (humanVsMachine === 'computer') { computerWins += 1; } return [playerWins, computerWins]; } } console.log(playToFive());可能会因已经无效的条件而被调用 - 这意味着意图被打破。

我的逻辑出了什么问题?

2 个答案:

答案 0 :(得分:2)

Object#wait()Condition#await()唤醒意味着重新获取相关锁定。 据推测,只有在拥有锁时才能修改<some condition>因此,如果现在醒来的线程拥有锁,则其他任何线程都不能将条件更改为false。

答案 1 :(得分:2)

来自wait()的{​​{3}}:

  

当前线程必须拥有此对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法通知等待此对象监视器上的线程唤醒notifyAll方法。然后线程等待,直到它可以重新获得监视器的所有权并继续执行。

(强调我的)

换句话说,如果没有synchronized块,您的代码将抛出IllegalMonitorStateException。另一方面, synchronized,您的状况将通过wait();电话原子检查。

这并不意味着你没有任何问题,因为这里的“原子”只是关于你正在同步的对象(在你的情况下是this),而只是相对于其他同步访问宾语。如果您的条件取决于不同的对象,或者您在其他地方没有同步的情况下访问该对象,则事情可能会变坏。因此,不要这样做。

使用LockCondition s的原因相同。 docs条件变量派生自锁定对象,synchronized / wait / notify类似于lock; unlock / {{1} } / await