1

私はJAVA、特に並行性にかなり慣れていないので、おそらく/うまくいけば、これはかなり単純な問題です。

基本的に私のメインスレッドから私はこれを持っています:

public void playerTurn(Move move)
{

  // Wait until able to move
  while( !gameRoom.game.getCurrentPlayer().getAllowMove() )
  {
    try {
      Thread.sleep(200);
      trace("waiting for player to be available");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  gameRoom.getGame().handle(move);
}

gameRoom.getGame() は独自のスレッドにあります。gameRoom.getGame().handle() は同期されています gameRoom.game.getCurrentPlayer() は gameRoom.getGame() の変数上にあり、同じスレッドにあります

allowMoves は、handle(move) が呼び出されるとすぐに false に設定され、移動の処理が完了すると true に戻ります。

playerTurn() を複数回呼び出します。私は実際に SmartFoxServer 拡張機能からそれを呼び出します。リクエストを受信すると、多くの場合、立て続けに呼び出します。

私の問題は、ほとんどの場合うまくいくことです。ただし、allowMoves が false である必要がある場合でも、複数のハンドル (移動) 呼び出しを発行している場合があります。それが再び真実になるのを待っていません。別のハンドル (移動) が呼び出される前に、ゲーム スレッドが allowMoves を設定する機会がなかった可能性があると考えました。allowMoves に volatile を追加し、ゲーム スレッドの関数が同期に設定されていることを確認しました。しかし、問題はまだ起こっています。

これらは私の Game クラスにあります:

synchronized public void handle(Object msg)
{
  lastMessage = msg;
  notify();
} 

synchronized public Move move() throws InterruptedException
{
  while (true)
  {
   allowMoves = true;
   System.out.print(" waiting for move()...");
   wait();
   allowMoves = false;
   if (lastMessage instanceof Move)
   {
    System.out.print(" process move()...");
    Move m = (Move) lastMessage;
    return m;
   }
  }
}

public volatile boolean allowMoves;
synchronized public boolean getAllowMoves()
{
  return allowMoves;
}

私が言ったように、私はこれに不慣れで、おそらく自分よりも少し進んでいます(いつものように、深いところに飛び込むのが私のスタイルで、とにかく迅速な学習曲線には最適です).

あなたの助けに乾杯。

4

3 に答える 3

1

問題は synchronized、2つの異なるオブジェクトでメソッドを使用していることです。

 gameRoom.game.getCurrentPlayer().getAllowMove()<-- This is synchronized on 
                                                    CurrentPlayer instance.
 gameRoom.getGame().handle(move)<-- This is synchronized on `gameRoom.getGame()`

これはあなたの問題です。フィールドは可視性のセマンティクスを保証するものであるsynchronizedため、キーワードは必要ありません。getAllowMovesvolatilevolatile

public boolean getAllowMoves() {
    return allowMoves;
}
于 2012-10-25T11:33:11.147 に答える
1

これが役立つかどうかはわかりませんが、andの代わりにAtomicBooleanを使用するとどうなりますか?と書いてあります。synchronizedvolatilelock-free and thread-safe

于 2012-10-25T12:02:00.053 に答える
0

リソース管理専用のプリミティブがあります-セマフォ

必要がある

  • 許可を 1 に設定してセマフォを作成する
  • 動きを探すときは acquire を使用します
  • 移動完了後にリリースを使用

そのため、ハンドル メソッドの 2 つの同時呼び出しが表示されることに直面することはありません。

于 2012-10-25T11:50:05.563 に答える