Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在此处使用锁/同步_Java_Multithreading - Fatal编程技术网

Java 如何在此处使用锁/同步

Java 如何在此处使用锁/同步,java,multithreading,Java,Multithreading,我这里有这个代码块,我需要确保rankedPlayersWaitingForMatch在线程之间正确同步。我本来打算使用synchronize,但我认为在这里不起作用,因为if语句中使用了变量。我在网上读到关于final Lock=new ReentrantLock()但是我有点困惑,在这种情况下如何正确地使用try/finally块。我能举个简单的例子吗?谢谢 // start synchronization if (rankedPlayersWaitingForMatch.get(ranke

我这里有这个代码块,我需要确保
rankedPlayersWaitingForMatch
在线程之间正确同步。我本来打算使用
synchronize
,但我认为在这里不起作用,因为
if
语句中使用了变量。我在网上读到关于
final 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
  // ...
}

有两种方法可以同步——您想要的是

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
}
需要注意的是,同步的是代码块,而不是数据(即使目标是保护数据)。因此,您还需要同步与该变量相关的任何其他代码区域,例如,任何代码都会将新玩家添加到队列中


有更复杂的方法可以执行得更好,但这一种方法很有效,而且很容易得到正确的结果。

有两种方法可以同步——您想要的方法是

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
}
需要注意的是,同步的是代码块,而不是数据(即使目标是保护数据)。因此,您还需要同步与该变量相关的任何其他代码区域,例如,任何代码都会将新玩家添加到队列中


有更复杂的方法可以更好地执行,但这一种方法很有效,而且很容易得到正确的结果。

以下是您想要做的:

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{
  // ...
}

以下是您想要做的:

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{
  // ...
}

虽然flag的想法可行,但最简单的解决方案是重写代码

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
}

这更具可读性,也更容易获得正确的信息。

当标志思想起作用时,最简单的解决方案是重写代码

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
}


这更具可读性,也更容易获得正确信息。

您还可以使用Collection.synchronizedMap()或者java.util.concurrent中的映射类,如果执行符合您的需要。
但是我认为这在这里不起作用,因为if语句中使用了变量
为什么不同步
if
呢?@DarthAndroid,这对他毫无帮助。多个线程将能够同时通过
size()>=2
检查。为什么您认为
synchronized
无法使用
if
语句?只需将
if
语句包装在
synchronized(rankedPlayersWaitingForMatch){…}
块中。当然,这只是故事的一半,因为您需要正确地同步对共享对象的所有访问。这里最重要的一个词是“正确”。在多线程系统中,同步必须是设计的有机组成部分,而不仅仅是事后考虑。@iCode4Food请检查编辑,对不起,我忘了写一些东西。您也可以使用Collection.synchronizedMap()或者java.util.concurrent中的映射类,如果执行符合您的需要。
但是我认为这在这里不起作用,因为if语句中使用了变量
为什么不同步
if
呢?@DarthAndroid,这对他毫无帮助。多个线程将能够同时通过
size()>=2
检查。为什么您认为
synchronized
无法使用
if
语句?只需将
if
语句包装在
synchronized(rankedPlayersWaitingForMatch){…}
块中。当然,这只是故事的一半,因为您需要正确地同步对共享对象的所有访问。这里最重要的一个词是“正确”。在多线程系统中,同步必须是设计的有机组成部分,而不仅仅是事后考虑。@iCode4Food请检查编辑,对不起,我忘了写一些我不好的东西,你能检查我所做的编辑吗。我忘了一条关键信息。这仍然使他的其余“if”子句保持同步,他说他不想要。一旦你改变了,你的答案就会和我的一样。我想你错过了一个事实,那就是在我给出最初的答案后,问题发生了变化。你的答案是正确的。我的错,你能检查一下我的编辑吗。我忘了一条关键信息。这仍然使他的其余“if”子句保持同步,他说他不想要。一旦你改变了,你的答案就会和我的一样。我想你错过了一个事实,那就是在我给出最初的答案后,问题发生了变化。你的答案是正确的。好主意!这正是我需要它做的。谢谢:)好主意!这正是我需要它做的。谢谢:)此解决方案将更流畅地使用具有特殊元组支持的语言+1为讨论添加一个新想法。这里代码样式的优点是,如果代码中有其他地方选择成对的玩家,那么它封装了这个概念。如果这不太可能,我就不麻烦了。@MelNicholson是真的,但这是我们要做的:)我试图表达的是我在评论中已经写过的:同步应该是设计的一个重要部分,否则你肯定会遇到麻烦。我相信我们都尝试过另一种选择,诱惑是非常强烈的(“我只需要在这里和那里添加几个同步的,它很快就会是线程安全的。”),我当然尝试过。我得到的教训是:不要……)这种解决方案在支持特殊元组的语言中会更加流畅+1为讨论添加一个新想法。这里代码样式的优点是,如果代码中有其他地方选择成对的玩家,那么它封装了这个概念。如果这不太可能,我就不麻烦了。@MelNicholson是真的,但这是我们要做的:)我试图表达的是我在评论中已经写过的:同步应该是设计的一个重要部分,否则你肯定会遇到麻烦。我相信我们都尝试过另一种选择,诱惑是非常强烈的