我正在開發一款Android遊戲,並且有一個奇怪的問題,偶爾遊戲會在彈回生命之前變得無響應很長一段時間。據我所知,這種停頓,如果它發生,只會在遊戲啓動時發生。一旦正常運行,遊戲似乎表現自己。即使其他線程沒有鎖定,也需要等待同步對象
經過一番調查後,似乎onTouchEvent回調正在被阻止,試圖獲取它與遊戲線程共享的同步對象的鎖定。同時遊戲線程正常運行,並且不會長時間保持對同步對象的鎖定。
這是我的理解是,doTouchEvent中的同步塊會在遊戲線程釋放該鎖後立即獲取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;
}
}
起初,我已經在mSurfaceHolder上同步所有內容,但爲doTouchEvent添加了單獨的同步對象,以減少可能被阻止的數量(儘管不是太多)。 – threeshinyapples 2012-02-25 20:26:33
對不起,提交得太快,無法編輯,因爲太多的時間過去... 我意識到最好的解決方案將涉及到一個輕微的重新設計,以確保觸摸事件可以安全地處理,而不依賴於同步。 但我真的很想知道爲什麼我看到這種情況,UI線程似乎無法獲得它的同步鎖定很長一段時間,即使遊戲線程給了它大量的機會。 – threeshinyapples 2012-02-25 20:34:27