1

我在这里有这个代码块,我需要确保rankedPlayersWaitingForMatch线程之间正确同步。我打算使用synchronize,但我认为不会在这里工作,因为if语句中使用了变量。我在网上阅读了有关但我对如何在这种情况下正确使用该块final Lock lock = new ReentrantLock();感到有点困惑。try/finally我可以举个简单的例子吗?谢谢

// start synchronization
if (rankedPlayersWaitingForMatch.get(rankedType).size() >= 2) {
  Player player1 = rankedPlayersWaitingForMatch.get(rankedType).remove();
  Player player2 = rankedPlayersWaitingForMatch.get(rankedType).remove();
  // end synchronization
  // ... I don't want this all to be synchronized, just after the first 2 remove()
} else {
  // end synchronization
  // ...
}
4

3 回答 3

4

有两种方法synchronize- 你想要的一种是......

boolean shortQueue = true;
synchronize (rankedPlayersWaitingForMatch) {     
  if (rankedPlayersWaitingForMatch.get(rankedType).size() >= 2) {
    shortQueue = false;
    Player player1 = rankedPlayersWaitingForMatch.get(rankedType).remove();
    Player player2 = rankedPlayersWaitingForMatch.get(rankedType).remove();
  } 
}
if (shortQueue) {
    // this was your else clause
} else {
    // this was the rest of the processing
}

需要注意的是,您同步的是代码块,而不是数据(即使目标是保护数据)。因此,您还需要同步涉及该变量的任何其他代码区域,例如将新玩家添加到队列中的任何代码。

有更复杂的方法可以更好地执行,但是这个方法会起作用并且很容易得到正确的。

于 2013-07-01T16:16:31.213 回答
3

这是您想要执行的操作:

boolean has_players = false;
Player player1;
Player player2;
synchronize (rankedPlayersWaitingForMatch) {
  if (rankedPlayersWaitingForMatch.get(rankedType).size() >= 2) {
    player1 = rankedPlayersWaitingForMatch.get(rankedType).remove();
    player2 = rankedPlayersWaitingForMatch.get(rankedType).remove();
    has_players = true;
  }
}

if(has_players){
  // ... I don't want this all to be synchronized, just after the first 2 remove()
}
else{
  // ...
}
于 2013-07-01T16:19:24.920 回答
2

虽然标志的想法有效,但最简单的解决方案是重写代码。

private PlayerPair pickPlayers( Type rankedType ) {
  synchronized( rankedPlayersWaitingForMatch ) {
    if (rankedPlayersWaitingForMatch.get(rankedType).size() >= 2) {
      Player player1 = rankedPlayersWaitingForMatch.get(rankedType).remove();
      Player player2 = rankedPlayersWaitingForMatch.get(rankedType).remove();
      return new PlayerPair( player1, player2 );
    }
    return null;
  }
}

在你的调用代码中......

PlayerPair pair = pickPlayers( rankedType );
if( pair != null ) { 
   ...do unsynchronised stuff here...
} else {
   ...more unsynchronised stuff
}

这更具可读性并且更容易正确。

于 2013-07-01T16:24:19.513 回答