Android2.1源码中的一个bug
2010-10-14 06:16:00 来源:本站整理Log.i(TAG, "Telephony Registry");
ServiceManager.addService("telephony.registry",
new TelephonyRegistry(context));
后经仔细分析ActivityManagerService的main方法源码
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
发现有多线程同步的问题。main方法中有代码如下:
AThread thr = new AThread();
thr.start();
synchronized (thr) {
while (thr.mService == null) {
try {
thr.wait();
} catch (InterruptedException e) {
}
}
}
……………
thr.mRead = true;
notifyAll();
我们非常容易看出这段代码的意思是启动一个线程thr,然后等待线程线程初始化完成thr.mService变量再继续执行。
那么我们再分析一下AThread的run方法。
Looper.prepare();
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
ActivityManagerService m = new ActivityManagerService();
synchronized (this) {
mService = m;
notifyAll();
}
synchronized (this) {
while (!mReady) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
Looper.loop();
表面上看来这段代码也没有问题。先初始化mService通知ActivityManagerService的主线程(notifyAll()),然后等待主线程执行,并重置了mRead之后,再继续执行。
问题出在notifyAll之后,多线程编程最重要的就是要注意竞争关系。假如AThread调用notifyAll之后,主线程没有得到调度,还是在调度AThread将会怎么样呢?第一次AThread的第一次wait成功返回(对主线程的通知,被他自己给截获了),第二次就加锁。这时开始调度主线程,主线程wait发现还是没有通知,那就继续等待下去,变成了死锁。本人对Java不是非常熟悉,以上面的方式使用wait/notify /notifyAll方法肯定是不正确的。如果我的理解有问题,请Java达人赐教。
为了确保代码的修改量最小,我选用了权宜之计。解决方法是在notifyAll之后sleep一下,sleep之后当前线程将会释放调度权。修改后的代码如下:
更多精彩
赞助商链接