我有一个对象保存对象的strong
引用:
@property (nonatomic, strong) NSObject *thing;
在其他地方,我有一个传递对象引用的方法:
[thirdObject doSomething:secondObject.thing];
在一个案例中(百万或十亿),第三个对象最终使用悬空指针,因为对象被交换并且没有所有者。
我可以通过这样做来避免这种情况吗?这与ARC不同吗?
NSObject *thing = secondObject.thing
[thirdObject doSomething:secondObject.thing];
如果没有,我该如何避免这种情况?
编辑:消息是“消息发送到解除分配的实例0xwhatever”
答案 0 :(得分:5)
如果不应用某种线程安全性,则无法在多个线程上读取和写入属性。现在原则上,对于像字符串这样的简单对象,也许仅仅应用atomic
就足够了。有关详细信息,请参阅What's the difference between the atomic and nonatomic attributes?。
atomic
。我知道它的作用,但它似乎是一种繁琐的方式来达到你真正想要的东西(并且经常会比你想要的少)。而且这不是一个非常普遍的解决方案;我无法自定义atomic
访问者“一点”(比如添加setNeedsDisplay
等)。
这就是我喜欢基于队列的访问器的原因。他们的工作多一点,但是他们对很多问题都有效。
@property (nonatomic, readwrite, strong) dispatch_queue_t thingQueue;
@property (nonatomic, strong) NSObject *thing;
- (id)init {
...
_thingQueue = dispatch_queue_create("...", DISPATCH_QUEUE_CONCURRENT);
...
}
- (NSObject *)thing {
__block NSObject *thing;
dispatch_sync(self.thingQueue, ^{
thing = _thing;
});
return thing;
}
- (void)setThing:(NSObject *)thing {
dispatch_barrier_async(self.thingQueue, ^{
_thing = thing;
});
}
我喜欢这个系统的是它允许所有读者并行。当作家试图进行更新时,无论涉及多少读者,都保证不会饿死。它总是快速返回。当值发生变化时,队列中还有一个明确的点,以便在编写者之前请求值的读者将始终获得旧值,并且在编写者之后的读者将始终获得新值,无论有多少争用在队列中。
关键是getter是同步的,所以它会等到它可以获得值,并且setter包含一个屏障。屏障意味着“在我运行时,不会从此队列中安排其他块”。因此,您有一堆并行运行的读取器块,然后出现了setter屏障并等待所有读者完成。然后它单独运行,设置值,然后它后面的读者可以再次并行运行。