如何在这里使用锁/同步

时间:2013-07-01 16:10:21

标签: java multithreading

我在这里有这个代码块,我需要确保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
  // ...
}

3 个答案:

答案 0 :(得分: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
}

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

有更复杂的方法可以表现得更好,但是这个方法会起作用并且很容易纠正。

答案 1 :(得分: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{
  // ...
}

答案 2 :(得分: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
}

这更容易理解,更容易理解。