我的应用程序中有2个线程,一个游戏更新线程和渲染/ IO /主线程。 我的更新线程更新游戏状态,渲染线程根据游戏状态模型的更新值和存储在对象(gameEngine)中的一些其他变量来渲染场景。
渲染线程在游戏线程仍在更新时执行,这是一个问题,所以在我看来解决方案是使用@synchronized这样:
@synchronized(gameEngine)
{
[gameEngine update];
nextUpdate = now + GAME_UPDATE_INTERVAL;
gameEngine.lastGameUpdateInterval = now - lastUpdate;
gameEngine.lastGameUpdateTime = now;
lastUpdate = now;
}
但是渲染线程仍然访问-update
和块的最后3行之间的gameEngine对象。这是为什么?
答案 0 :(得分:10)
@synchronized
不会阻止其他线程访问gameEngine
。它只是阻止具有相同对象的其他@synchronized
。这意味着在
// thread A:
@synchronized(a) {
do_A(a);
}
...
// thread B:
do_B(a);
do_A
和do_B
可以一起发生,但在
// thread A:
@synchronized(a) {
do_A(a);
}
...
// thread B:
@syncrhonized(a) {
do_B(a);
}
do_A
和do_B
将始终按顺序执行。
答案 1 :(得分:0)
你不应该锁定gameEngine - @KennyTM解释了我认为对你的问题的正确答案,但是实现它会导致游戏引擎或渲染器只能在给定时间执行,使它基本上是单线程的。你应该做的是使用一个不可变的状态对象,它可能是gameEngine的ivar,但应该是非原子的,在render函数中你可以像这样获取状态
State *state = [[gameEngine state] retain];
然后使用state,完成后释放它。当gameEngine执行更新时,它不应该改变其状态ivar中的数据,这可能是渲染器使用的,但可以复制它。要设置状态,它应该
State *oldState = state;
state = newState; //newState should have a retainCount of 1
[oldState release];
因为如果在将状态设置为newState之前释放oldState,那么渲染器可能会获得oldState,它刚刚被释放,导致Bad Things。