首先让我引用Apple Threading Programming Guide中的一章:
意识到代码正确性的威胁
当使用锁和记忆障碍时,你应该经常仔细考虑他们的 放置在您的代码中。即使是看起来很好的锁也可以 让你陷入虚假的安全感。以下系列 示例试图通过指出缺陷来说明这个问题 看似无害的代码。基本前提是你有一个 包含一组不可变对象的可变数组。假设你想要 调用数组中第一个对象的方法。你可能会这样做 使用以下代码:
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[arrayLock unlock];
[anObject doSomething];
因为数组是可变的,所以数组周围的锁定会阻止其他数组 修改数组的线程,直到获得所需的对象。和 因为您检索的对象本身是不可变的,所以锁不是 需要调用doSomething方法。
但是前面的例子存在问题。如果发生什么 你释放锁,另一个线程进入并删除所有 在你有机会执行之前,数组中的对象 doSomething方法?在没有垃圾收集的应用程序中 你的代码所持有的对象可以被释放,留下一个对象 指向无效的内存地址。要解决这个问题,你可以 决定简单地重新安排现有代码并释放锁定 在你打电话给doSomething之后,如下所示:
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[anObject doSomething];
[arrayLock unlock];
通过在锁内移动doSomething调用,您的代码可以保证 调用方法时对象仍然有效。 不幸的是,如果doSomething方法需要很长时间才能执行, 这可能会导致您的代码长时间保持锁定 可能会造成性能瓶颈。
代码的问题不是关键区域不好 定义,但实际问题没有被理解。真的 问题是仅由内存触发的内存管理问题 存在其他线程。因为它可以被另一个人释放 线程,更好的解决方案是在释放之前保留anObject 锁。该解决方案解决了对象的真正问题 发布并在不引入潜在性能的情况下发布 罚。
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[anObject retain];
[arrayLock unlock];
[anObject doSomething];
[anObject release];
问题是:使用ARC时有什么方法可以解决问题吗?
答案 0 :(得分:4)
ARC会自动为您解决此问题;默认情况下,每个指针都是一个strong
指针,这意味着在完成使用该指针之前,保证保留该对象。
这意味着无论何时从数组中获取对象,ARC始终会保留该对象。即使稍后从数组中删除对象,这也可以保证其生命周期。