2013-07-01 39 views
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 
    // ... 
} 
+0

如果执行符合您的需要,也可以使用Collection.synchronizedMap()或java.util.concurrent中的映射类。 –

+0

'但我不认为会在这里工作,因为在if语句中使用了变量'为什么不同步'if'呢? –

+0

@DarthAndroid根本无法帮助他。多个线程可以同时通过'size()> = 2'检查。 –

回答

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

好主意!这应该正是我需要它做的。感谢:) – MasterGberry

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 
} 

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

有更复杂的方法会表现更好,但是这个方法会工作并且很容易得到正确。

+0

我的不好,你能检查我所做的编辑吗?我忘记了一条关键信息。 – MasterGberry

+0

啊...编辑修正。 –

+0

这仍然使他的“if”条款的其余部分同步,他表示他不想要。一旦你改变了,你的答案就会和我一样。 –

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 
} 

这是更具可读性,更容易得到正确的。

+0

+1随时为了可读性。 – nullpotent

+0

这个解决方案对于具有ad-hoc元组支持的语言会更流利。 +1为讨论添加新想法。这里的代码风格的优点在于,如果在代码中有其他地方选择成对玩家,它就会封装概念。如果不可能的话,我不会打扰。 –

+0

@MelNicholson真的,但这是我们要做的:)我试图传达的真正是我已经写在评论中的内容:同步应该是设计的重要组成部分,否则,必然会遇到一个令人讨厌的问题。我确定我们都尝试了另一种方式,诱惑力非常强(“我只是在这里和那里添加一些同步的数据,并且很快就会线程安全。”),我当然有。我学到的教训是:不。 :) – biziclop