gpt4 book ai didi

android - 长时间等待同步对象,即使其他线程没有持有锁

转载 作者:行者123 更新时间:2023-11-30 04:19:48 25 4
gpt4 key购买 nike

我正在开发一款 Android 游戏,遇到一个奇怪的问题,有时游戏会在很长一段时间内没有响应,然后才恢复正常。据我所知,这种暂停如果真的发生的话,只会在游戏启动时发生。一旦正常运行,游戏似乎会自行运行。

经过一些调查,似乎 onTouchEvent 回调在尝试获取它与游戏线程共享的同步对象上的锁时被阻塞。同时游戏线程正常运行,不会长时间持有同步对象的锁。

据我了解,doTouchEvent 中的同步块(synchronized block)会在 mSyncObject 上的锁被游戏线程释放后立即获取该锁。但在某些情况下,在 doTouchEvent 最终能够获取其锁之前,游戏线程似乎能够获取和释放锁数百次。

没有其他代码使用同一对象进行同步。

我已经复制了下面的相关代码。据我所知,它没有做任何异常的事情,所以我对我所看到的奇怪行为感到有些困惑。

在此方面提供任何帮助,我们将不胜感激。提前致谢!

class GameThread extends Thread {

// ...some methods and members omitted...

private volatile int mFrameCount = 0;
private Object mSyncObject = new Object();

@Override
public void run() {
while (!mShutDown) {
Canvas canvas = null;
long timestampA = System.currentTimeMillis();
try {
synchronized (mSurfaceHolder) {
canvas = mSurfaceHolder.lockCanvas(null);
// Synchronized on our object...
synchronized (mSyncObject) {
long now = System.currentTimeMillis();
if ((now > mLastTime) && !mPaused) {
double timestep = (double) (now - mLastTime) / 1000.0;
mGame.update(timestep);
}
mLastTime = now;
if (canvas != null) {
mGame.draw(canvas);
}
}
}
} finally {
if (canvas != null) {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}

// have tried inserting a sleep() here, but it didn’t help

++mFrameCount;
}
}


// Called from the UI thread
public boolean doTouchEvent(MotionEvent event) {
boolean result = false;

// Synchronized on our object...
// The game loop in run() acquires and releases a lock
// on this object on every frame, so would expect to be
// blocked here for no longer than one frame.
// However, on occasions have been blocked here for over
// 2000 iterations of the game loop.
int frameCount = mFrameCount;
synchronized (mSyncObject) {
int framesWaited = mFrameCount - frameCount;
if (framesWaited > 1) {
Log.i("Block", "doTouchEvent waited " + framesWaited + " frames for lock");
}

if (!(mPaused || mShutDown)) {
result = mGame.doTouchEvent(event);
}
}
return result;
}

}

最佳答案

看起来这个问题是由于同步在等待线程获取锁的顺序时不能提供公平性保证这一事实。事实上,如果另一个 cpu 密集型线程重复获取和释放锁,则线程可能会无限期地等待锁。

看到这个线程讨论完全相同的问题...

http://groups.google.com/group/android-developers/browse_frm/thread/ffe76e4a433c8675/f424fb7dc3baeb10

...这里是一个线程安全但无同步解决方案的示例。

http://blog.tomgibara.com/post/208684592/avoiding-starvation

在遇到上述问题之前,我更改了代码以使用 ConcurrentLinkedQueue 在线程之间传递运动事件,这似乎也能有效消除停顿。

关于android - 长时间等待同步对象,即使其他线程没有持有锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9447615/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com