一处死锁分析
最近在进行回归测试的时候,QA同学反映有一处死锁,导致大量线程Hang死。通过pstack查看后,发现如下可疑的两个线程:

Thread 1: 1. Hold A.ReadLock, 2. Request B.ReadLock
Thread 2: 1. Hold B.ReadLock, 2. Request A.WriteLock
看到此处就觉得比较奇怪,Thread2被Hang住很正常,因为A的读锁被Thread1占有了,此时无法加上A的写锁,但是为什么Thread 1会被锁死呢?因为此时B的读锁最少被Thread 2加上了,说明没有写线程占有写锁。且其他大量线程都被锁死在请求B的读锁的时候。
排除掉所有那些请求B的读锁被Hang死的线程后,发现了一个可疑的线程,这个线程Hang在如下位置
Thread 3: Request B.WriteLock
即存在一个线程在请求B的写锁,且处于等待的过程中。疑点比较明显,于是gdb之后,打印了一下这个pthread_rwlock_t的属性,发现其__rw_kind的属性值是1,顺藤摸瓜,发现这个读写锁在初始化的时候使用了如下过程:
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr)
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_rwlock_init(&_rwlock, &attr);
其中PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP表明写锁优先的模式,即有写者等待时,所有读者被阻塞,所以因为Thread 3在获取B的写锁,则Thread 1无法获取B的读锁,从而导致A的读锁不会被释放,此种情况Thread 2无法获取A的写锁,也不会释放B的读锁,导致死锁。
解完Bug后,大呼原来多线程情况下,两个以前线程也有可能在某些情况下造成死锁。即只要有加锁顺序不一致的情况,且有读写锁混合的情况下,如果有写锁优先的情况,也有可能导致死锁。


终于在这个26岁生日的时候,完成了一个小小的心愿,入了第一个iDevice,泡泡送了我一个iPod Touch 4。通过这段时间的使用,我对iOS总算有了一个比较切身的体会。当年买Nexus One的时候写过一篇评测,今天也写一篇吧,算是从一个互联网从业人员的角度来观察苹果的产品,并且尽量从中立的角度来比较一下iOS(iPod Touch 4)与Android(Nexus One)的优缺点。
最新评论