dealloc调用与运行方法相同的线程会因竞争条件导致崩溃,这是预期的吗?

时间:2011-12-24 23:52:33

标签: objective-c ios multithreading thread-safety

我有一个名为MadsAdViewController的对象,它以异步方式请求广告,并在方法didReceiveResponse上回调。在具有大量内存使用量的应用程序中,dealloc方法被称为非常快,有时甚至在didReceiveResponse方法仍在运行时。这会导致崩溃,因为我称之为竞争条件。如输出所示,在主线程上调用didReceiveResponsedealloc

为什么dealloc不等待方法完成?为什么@synchronized块不起作用?我该如何解决这个问题?

-(void)didReceiveResponse:(MadsAdResponse*) inAdResponse {
    NSLog(@"didReceiveResponse: main thread? = %i, address = %p", [NSThread isMainThread], self);
    @synchronized (self) {
        //... (lots of stuff that takes a while)
        [self logEvent:logAction eventName:EVENT_INIT action:ACTION_VIEW extra:nil];  
    }
    NSLog(@"done with didReceiveResponse response")
}

- (void)dealloc {
    @synchronized (self) {
        NSLog(@"in sync block in dealloc of object %p", self);
        //lots of releases
    }
    [super dealloc]
}

这是输出:

didReceiveResponse: main thread? = 1, address = 0x139d50b0
in sync block in dealloc of object 0x139d50b0

然后应用程序崩溃:

*** -[[MadsAdViewController logEvent:eventName:action:extra:]: message sent to deallocated instance 0x139d50b0

1 个答案:

答案 0 :(得分:0)

好的,转而在块和上面列出的这段代码之间进行了很好的交互。

对于上下文,我们的图书馆被外部方以我们不推荐的方式使用。

这就是它周围发生的事情:

XXXMadsAdViewController *adViewController = [[[XXXMadsAdViewController alloc]init]autorelease];
self.adViewController = adViewController;
[self.adViewController loadAdWithCompletionHandler:^(BOOL success) {
     //stuff
}];

XXXMadsAdViewController扩展了MadsAdViewController ,因为它是委托以接收方法调用didReceivePartialAd。我在方法[self.delegate didReceivePartialAd]中调用了didReceiveResponse,我在原始问题中未包含该内容,而 [self logEvent];

之前称为

现在,有时self.adViewController已经被释放,但是这个块仍在等待回调。在didReceivePartialAd上回调时,块被处理,self.adViewController再次释放,应用程序崩溃。

我通过将didReceivePartialAd作为方法didReceiveResponse的最后一个语句来解决问题。

谢谢你们,没有你的指示,我仍然认为这是一场竞争条件!