What's wrong with my @synchronized block?

I have 2 threads in my application, game update thread and render / IO / main thread. My update thread updates the game state and the render thread renders the scene based on the updated values ​​of the game state models and a few other variables stored inside the object (gameEngine).

The render thread is running while the game thread is still updating, which is a problem, so it seemed to me that the solution was to use @synchronized like this:

        @synchronized(gameEngine)
        {
            [gameEngine update];

            nextUpdate = now + GAME_UPDATE_INTERVAL;

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

      

But the render thread still accesses the gameEngine object between -update

and the last three lines of the block. Why is this?

+2


a source to share


2 answers


@synchronized

does not block other threads from accessing gameEngine

. It just blocks others @synchronized

with the same object. This means that in

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

      

do_A

and do_B

can occur together, but in



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

      

do_A

and do_B

will always run sequentially.

+10


a source


You shouldn't block the gameEngine - @KennyTM explained what I think is the correct answer to your question, however implementing it will result in only the game engine or rendering being able to execute at a given point in time, making it essentially single threaded. What you should be doing is use an immutable state object, which can be an ivar of the gameEngine, but should be non- atomic , where in the render function you grab a state like this

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

      

and then use the state by releasing it when done. When the gameEngine does an update, it should not mutate data in its ivar state, which can be used by the renderer but can make a copy of it. To establish a state, it must



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

      

because if you release oldState before setting the state to newState, the renderer might get oldState that was just released, resulting in Bad Things.

0


a source







All Articles