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是真的,但这是我们要做的:)我试图表达的是我在评论中已经写过的:同步应该是设计的一个重要部分,否则你肯定会遇到麻烦。我相信我们都尝试过另一种选择,诱惑是非常强烈的