一个Java线程死锁的真实案例

前一段时间在做的产品中出现一个BUG,现象是界面起不来,显出Splash Screen后就停在那里。经过分析,调试后发现是传说中的线程死锁。一个已经开发了7,8年的东西,这种问题到现在才无意中暴露出来。

java 代码
  1. public class Main{   
  2.   
  3.     public synchronized void initializeDomainModel() {   
  4.         ApplicationModel model = new ApplicationModel(this);           
  5.       setDomainModel(model);   
  6.           
  7.       model.startSession(name, port, nullnull);   
  8.       model.addPropertyChangeListener(getPanel());   
  9.         try {   
  10.             wait(10000);   
  11.       } catch (InterruptedException e) {   
  12.       }   
  13.     }   
  14. }   
  15.   
  16. public class ApplicationModel extends ...{   
  17.   
  18.   public ApplicationModel(Main m){   
  19.     application = m;   
  20.   }   
  21.   
  22.     public synchronized void startSession(String host, int port,   
  23.                                     String userName, String password) {   
  24.        
  25.         ...    
  26.         applicationInterface.getXXX(this);   
  27.        
  28.     }   
  29.        
  30.        
  31.     public synchronized void serverCallback(Response response, RequestNode node)   
  32.     {   
  33.         
  34.          ...   
  35.          if (application != null) {   
  36.             synchronized(application) {   
  37.                 application.notify();   
  38.             }   
  39.             connectToDb();   
  40.          }   
  41.          ///!   
  42.     }   
  43.        
  44.     public synchronized void addPropertyChangeListener(Listener l){   
  45.     }   
  46.     ...   
  47. }  

程序流程是这样的:

1. Main是程序入口,会启动主界面。 2.  startSession方法中的getXXX(this) 会向Server端发送请求,回调函数serverCallback由另一个线程负责调用。

问题分析:

程序停在36行,说明application,也就是Main对象上的锁没有被主线程释放,而主线程之所以没有走到第10行wait,是因为在第8行addPropertyChangeListener的时候发现其他线程在执行serverCallback占用了ApplicationModel对象的锁。

解决方法:

1。Main中不需要同步整个initializeDomainModel方法,只需要将wait放入同步块即可。 2。调换model.startSession和model.addPropertyChangeListener的顺序也可以解决

 

 

你可能感兴趣的:(Java)