2011-10-15 145 views
1

我目前(尝试)编程一个小游戏。我有一个小设计/死锁问题。杀死僵局

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

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

我相信死锁发生在线程的运行功能(两个同步)。问题是,wait()需要一个同步的线程,而ondraw()需要对这个表面持有者进行锁定。

我已经玩过一段时间了,但所有其他组合都会让事情变得更糟,我不知道如何解决这个问题。所以,请帮助:)

的主题:

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); 
       } 
      } 
     } 
    } 
} 
+0

我们需要查看其他线程的代码才能完全理解这一点。 – Delyan

回答

3

这就是问题所在:

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

     if(_suspended) 
      this.wait(); 

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

你取出两把锁 - this_surfaceHolder。您然后通过拨打wait释放this ...但您仍然拥有锁_surfaceHolder

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

在这一点上,你酿:

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

所以基本上你有两个线程,每个拥有一个LOC之前重新获得对this锁k并正在等待不可能发生的事情。这不是相当于正常的死锁(每个线程拥有一个锁并且正在等待另一个锁),但它非常接近。

道德:不要在当前“拥有”更多显示器的线程上调用wait(),因为它将调用wait()

+0

我认为是这样,但如何摆脱这个问题?通知需要线程上的锁定提取需要的水头? – Vulcano

+0

@ user989349:说实话,你不明白你想达到什么目的。但是eek--我没有看到你锁定了* thread *引用。首先,不要扩展Thread - 实现Runnable。其次,不要获取线程上的锁定或等待它。其他事情是这样做的,所以最好不要自己去做。什么是脉冲锁,而且它可以脉冲'_surfaceHolder'来代替? –

+0

澄清事情:我有一个地图,当我点击一个城镇,我想建立一些东西。当我离开城镇时,地图应该再次显示。所以地图绘制的第一部分是来自LunarLander(也有一个线程),第二部分来自Oracle(搜索threadPrimitiveDeprecation :)) – Vulcano