Objective-C多线程,当一个对象在其方法被执行时被释放会发生啥? (以及如何预防?)

Posted

技术标签:

【中文标题】Objective-C多线程,当一个对象在其方法被执行时被释放会发生啥? (以及如何预防?)【英文标题】:Objective-C multithreading, what happens when an object gets dealloc while its methods are being executed? (And how to prevent it?)Objective-C多线程,当一个对象在其方法被执行时被释放会发生什么? (以及如何预防?) 【发布时间】:2011-01-25 17:37:29 【问题描述】:

我正在为 iPhone 编写一个应用程序并遇到这种情况。

我有一个视图控制器 myViewController,只要用户点击屏幕上的“返回”按钮,它就会解除分配。后台有一个线程与远程服务器通信,并可能向 myViewController 中的方法、updateUI、方法发送消息。

如果后台线程在 myViewController 中发送 updateUI 消息,但用户恰好在正确的时间点按了“返回”按钮,导致 myViewController 在 updateUI 仍在执行时解除分配,会发生什么情况?

我的猜测是如果 updateUI 最终使用空指针,dealloc 方法将运行并且应用程序可能会崩溃。假设是这种情况,我目前的解决方案是:

[self retain];
// updateUI code here
[self release];

我不确定这是否是最好的解决方案,因为我觉得这是处理多线程时的常见问题。

我的假设正确吗?如果有,有没有更好的解决方案?

【问题讨论】:

【参考方案1】:

您所描述的内容称为“竞争条件”。竞态条件在测试中很难识别,一旦报告就很难追踪并重现,因为有时在调试器中执行可以有效地修改代码的执行方式(避免尝试重现的情况)。竞争条件是并发编程中的主要缺陷之一 - 使该领域看似难以做好。

原则上,最佳做法是尽量减少共享资源的使用,并严格限定在实现并发时如何协调共享。如果一个对象在多个线程之间共享,则每个线程都应该保留它,以确保在每个线程完成其处理时该对象保持在范围内。

Apple 一直在采取措施简化并发实施。这是熟悉 ios 主题的一个很好的起点。 http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40008091

注意 Objective-C 2.0 的属性可以支持原子操作(默认情况下是原子的,因此使用 nonatomic 关键字禁用此默认值)也很有用。 http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html

而且,这是线程的老派指南(不受欢迎的方法,但仍然有用的背景 - 一定要熟悉 NSLock)。 http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html%23//apple_ref/doc/uid/10000057i

【讨论】:

【参考方案2】:

当您的代码的某些部分依赖于另一个部分时,它应该保留这种依赖关系,直到不需要它为止。在您的情况下,后台工作人员应保留控制器,并仅在工作完成(或取消)时释放它。

【讨论】:

不要忘记充分考虑您的各种数据结构如何确保并发读/写的完整性......哦,顺便说一句,多线程很难。 :)。【参考方案3】:

如果您 dealloc 然后 nil 您的对象,那么这应该不是问题 - 您可以在 Objective-c 中向 nil 发送消息。

或者,如果您希望 viewController 获取消息并且您的目标是 iOs 4,您可以使用块和 GCD。块会自动保留对象,因此如果一个块引用了您的 viewController,即使 -(void)dealloc ; 已被调用,它也会根据需要保留它。

Here 是一个不错的 Block 教程

【讨论】:

【参考方案4】:

是的,您的应用会崩溃,可能与 EXC_BAD_ACCESS 类似。

就多线程而言,您将希望保留您的对象,直到对它们进行所有操作 进行防御性编程。在尝试操作对象之前检查对象是否存在。

【讨论】:

以上是关于Objective-C多线程,当一个对象在其方法被执行时被释放会发生啥? (以及如何预防?)的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 多线程

多线程

《Objective-C高级编程 iOS与OS X多线程和内存管理》读书笔记

《Objective-C高级编程 iOS与OS X多线程和内存管理》读书笔记

可以在调用实例方法时释放 Objective-C 对象吗?

如果对象在其方法执行完成之前被释放怎么办