2

アプリケーションには、ゲーム更新スレッドとレンダリング/IO/メインスレッドの2つのスレッドがあります。私の更新スレッドはゲームの状態を更新し、レンダリングスレッドは、ゲームの状態モデルの更新された値と、オブジェクト(gameEngine)内に格納されている他のいくつかの変数に基づいてシーンをレンダリングします。

ゲームスレッドの更新中にレンダリングスレッドが実行されるのは問題なので、解決策は次のように@synchronizedを使用することです。

        @synchronized(gameEngine)
        {
            [gameEngine update];

            nextUpdate = now + GAME_UPDATE_INTERVAL;

            gameEngine.lastGameUpdateInterval = now - lastUpdate;
            gameEngine.lastGameUpdateTime = now;
            lastUpdate = now;
        }

-updateただし、レンダリングスレッドは、ブロックの最後の3行との間でgameEngineオブジェクトにアクセスします。どうしてこれなの?

4

2 に答える 2

10

@synchronized他のスレッドがにアクセスするのをブロックしませんgameEngine@synchronized同じオブジェクトで他をブロックするだけです。つまり、

// thread A:
@synchronized(a) {
   do_A(a);
}
...
// thread B:
do_B(a);

do_Ado_B一緒に起こる可能性がありますが

// thread A:
@synchronized(a) {
   do_A(a);
}
...
// thread B:
@syncrhonized(a) {
   do_B(a);
}

do_Ado_B常に順次実行されます。

于 2010-05-16T19:08:46.330 に答える
0

gameEngineをロックするべきではありません-@KennyTMは、あなたの質問に対する正しい答えであると私が信じていることを説明しましたが、それを実装すると、ゲームエンジンまたはレンダラーのいずれかのみが特定の時間に実行できるようになり、本質的にそれができますシングルスレッド。実行する必要があるのは、不変の状態オブジェクトを使用することです。これは、gameEngineのivarである可能性がありますが、非アトミックである必要があります。レンダリング関数では、このように状態を取得します。

State *state = [[gameEngine state] retain];

次に状態を使用し、完了したら解放します。gameEngineが更新を実行するとき、レンダラーによって使用されている可能性のある状態ivarのデータを変更してはなりませんが、そのコピーを作成することはできます。状態を設定するには、

State *oldState = state;
state = newState; //newState should have a retainCount of 1
[oldState release];

状態をnewStateに設定する前にoldStateを解放すると、レンダラーがoldStateを取得する可能性がありますが、これは割り当てが解除されたばかりであり、BadThingsにつながる可能性があります。

于 2010-05-16T19:23:51.880 に答える