使用併發性時,始終難以給出良好的響應。這很大程度上取決於你真正在做什麼以及真正重要的事情。
從我的理解,一個球員的舉動包括:
1 Updading球員的位置。
2從前一場中移除玩家。
3將玩家添加到新的領域。
想象一下,你在同一時間,但AQUIRE只有一個使用幾個鎖在一個時間: - 另一名球員能夠很好地看在錯誤的時刻,基本上1 & 2或2 & 3.有些玩家之間可以出現已經disapeared從董事會爲例。
想象一下你做imbricked鎖定這樣的:
synchronized(player) {
synchronized(previousField) {
synchronized(nextField) {
...
}
}
}
問題是...它不工作,看執行這個命令爲2個線程:
Thread1 :
Lock player1
Lock previousField
Thread2 :
Lock nextField and see that player1 is not in nextField.
Try to lock previousField and so way for Thread1 to release it.
Thread1 :
Lock nextField
Remove player1 from previous field and add it to next field.
Release all locks
Thread 2 :
Aquire Lock on previous field and read it :
線程2認爲玩家1從整個董事會中消失。如果這對於您的應用程序是個問題,那麼您不能使用此解決方案。
imbriqued鎖定的其他問題:線程可能會卡住。 想象2個播放器:它們在完全相同的時間交換它們的位置:
player1 aquire it's own position at the same time
player2 aquire it's own position at the same time
player1 try to acquire player2 position : wait for lock on player2 position.
player2 try to acquire player1 position : wait for lock on player1 position.
=>兩位球員將被阻止。
在我看來,最好的解決方案是隻使用一個鎖,用於整個遊戲狀態。
當玩家想要讀取狀態時,它會鎖定整個遊戲狀態(玩家&板),並根據自己的用法制作副本。然後它可以沒有任何鎖定地處理。
當玩家想要寫入狀態時,它會鎖定整個遊戲狀態,寫入新狀態,然後釋放鎖定。
=>鎖定限於遊戲狀態的讀/寫操作。玩家可以在自己的副本上進行「長時間」的棋盤狀態檢查。
這可以防止任何不一致的狀態,例如幾個字段中的玩家或沒有玩家,但不阻止該玩家可以使用「舊」狀態。
它可能看起來很奇怪,但它是一個象棋遊戲的典型案例。當你等待其他玩家移動時,你會看到棋盤在移動之前。你不知道其他玩家會做什麼動作,直到他終於移動了,你纔會處於「舊」狀態。
由於操作非常短暫,您可能會發現只使用一個全局鎖定表現得足夠好,以至於無法區分這些差異。使用一個鎖可能會限制自己每秒移動200K(這是否足夠?),但可能會簡化您的代碼,並且不會發生死鎖。 – 2011-01-05 12:52:06