杀死僵局

时间:2011-10-15 18:35:52

标签: java android multithreading deadlock

我正在(尝试)编写一个小游戏。我的设计/死锁问题很小。

当我按下一个按钮时,一个新的Intent打开,surfaceDestroyed设置一个布尔值来设置线程休眠。 当我返回时,线程获得通知信号。

大约90%的时间都可以使用(当我使用eclipse进行调试时,这是100%)。

我相信死锁发生在线程的run函数中(两个已同步)。问题是,wait()需要一个同步的线程,而ondraw()需要锁定在surfaceholder上。

我已经玩了一下,但所有其他组合使一切变得更糟,我不知道如何解决这个问题。所以请帮助:))

线程:

class BattleEarthThread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private BattleEarthView _battleEarthView;
    private boolean _run = false;
    private boolean _suspended = false;

    public SurfaceHolder getSurfaceHolder() {
        return _surfaceHolder;
    }

    public BattleEarthThread(SurfaceHolder surfaceHolder, BattleEarthView panel) {
        _surfaceHolder = surfaceHolder;
        _battleEarthView = panel;
    }

    public void setRunning(boolean run) {
        _run = run;
    }

    public void setSuspend(boolean suspend) {
        _suspended = suspend;
    }

    public boolean getSuspended() {
        return _run;
    }

    public boolean getRunning() {
        return _run;
    }

    @Override
    public void start() {
        super.start();
        _run = true;
    }

    @Override
    public void run() {
        Canvas c;
        while (_run) {
            c = null;
            try {
                synchronized(this)
                {
                        c = _surfaceHolder.lockCanvas(null);
                        synchronized (_surfaceHolder) {

                            if(_suspended)
                                this.wait();

                            else {
                                _battleEarthView.onDraw(c);
                            }
                        }
                    }
            } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                if (c != null) {
                    _surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:3)

这是问题所在:

synchronized(this) {
    c = _surfaceHolder.lockCanvas(null);
    synchronized (_surfaceHolder) {

        if(_suspended)
            this.wait();

        else {
            _battleEarthView.onDraw(c);
        }
    }
}

你正在取出两把锁 - this_surfaceHolder。然后,您通过调用this 释放锁定wait ...但您仍拥有_surfaceHolder的锁定。

现在假设另一个线程在同一个对象上执行相同的代码。它设法获取this的锁,因为此刻没有其他任何东西......但它在尝试获取_surfaceHolder时会阻塞,因为等待的线程拥有它。

此时,你被塞满了:

  • 没有线程可以获取正在等待的对象的锁定,因为第二个线程拥有它
  • 即使另一个线程可能脉冲该锁定,等待线程仍然需要在继续之前重新获取this上的锁定,这将无法

所以基本上你有两个线程,每个线程拥有一个锁,正等待一些不可能发生的事情。它不是相当正常的死锁(每个线程拥有一个锁并等待另一个锁)但它非常接近。

道德:不要在当前“拥有”更多监视器的线程上调用wait(),而不是要调用wait()的监视器。