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?
a source to share
@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.
a source to share
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.
a source to share