前一段时间在做的产品中出现一个BUG,现象是界面起不来,显出Splash Screen后就停在那里。经过分析,调试后发现是传说中的线程死锁。一个已经开发了7,8年的东西,这种问题到现在才无意中暴露出来。
java 代码
- public class Main{
- public synchronized void initializeDomainModel() {
- ApplicationModel model = new ApplicationModel(this);
- setDomainModel(model);
- model.startSession(name, port, null, null);
- model.addPropertyChangeListener(getPanel());
- try {
- wait(10000);
- } catch (InterruptedException e) {
- }
- }
- }
- public class ApplicationModel extends ...{
- public ApplicationModel(Main m){
- application = m;
- }
- public synchronized void startSession(String host, int port,
- String userName, String password) {
- ...
- applicationInterface.getXXX(this);
- }
- public synchronized void serverCallback(Response response, RequestNode node)
- {
- ...
- if (application != null) {
- synchronized(application) {
- application.notify();
- }
- connectToDb();
- }
- ///!
- }
- public synchronized void addPropertyChangeListener(Listener l){
- }
- ...
- }
程序流程是这样的:
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的顺序也可以解决