ARC的线程安全设计

时间:2013-05-30 12:56:13

标签: ios thread-safety automatic-ref-counting

首先让我引用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时有什么方法可以解决问题吗?

1 个答案:

答案 0 :(得分:4)

ARC会自动为您解决此问题;默认情况下,每个指针都是一个strong指针,这意味着在完成使用该指针之前,保证保留该对象。

这意味着无论何时从数组中获取对象,ARC始终会保留该对象。即使稍后从数组中删除对象,这也可以保证其生命周期。