2

我有一个对象包含对对象的strong引用:

@property (nonatomic, strong) NSObject *thing;

在其他地方,我有一个传递对象引用的方法:

[thirdObject doSomething:secondObject.thing];

在一种情况下(在一百万或十亿中),thirdObject 最终使用了一个悬空指针,因为该对象被交换并且没有所有者。

我可以通过这样做来避免这种情况吗?这对 ARC 有什么不同吗?

NSObject *thing = secondObject.thing
[thirdObject doSomething:secondObject.thing];

如果没有,我该如何避免这种情况?

编辑:消息是“发送到已释放实例 0xwhatever 的消息”

4

1 回答 1

7

如果不应用某种线程安全,就无法在多个线程上读取和写入属性。现在原则上,对于像字符串这样的简单对象,也许仅仅应用atomic就足够了。请参阅原子属性和非原子属性之间的区别是什么?更多关于它的作用。

坦白说,我真的很不喜欢atomic。我知道它的作用,但它似乎是一种获得你真正想要的东西的繁琐方式(而且往往最终比你想要的要少)。这不是一个非常通用的解决方案;我无法atomic“稍微”自定义访问器(例如添加 asetNeedsDisplay等)。

这就是为什么我喜欢基于队列的访问器。它们的工作量更大,但它们对很多问题都很有效。

@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;
  });
}

我喜欢这个系统的地方在于,它允许所有读者并行处理。当作者尝试进行更新时,无论涉及多少读者,都可以保证不会饿死。而且它总是很快返回。当值发生变化时,队列中还有一个明确的点,这样在 writer 之前请求 value 的读者总是会得到旧 value,而 writer 之后的读者总是会得到新 value,无论有多少争用在队列中。

关键是getter是同步的,所以会一直等到能拿到值,setter中包含了barrier。屏障意味着“在我运行时,不能从这个队列中安排其他块”。所以你有一堆并行运行的读取器块,然后设置器屏障出现并等待所有读取器完成。然后它单独运行,设置值,然后它后面的读者可以再次并行运行。

于 2013-04-10T21:41:22.833 回答