使用 ARC 避免出现悬空指针

2023-12-04

我有一个物体,里面有一个strong对对象的引用:

@property (nonatomic, strong) NSObject *thing;

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

[thirdObject doSomething:secondObject.thing];

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

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

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

如果不是,我该如何避免这种情况?

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


如果不应用某种线程安全性,则无法在多个线程上读取和写入属性。现在原则上,对于像字符串这样的简单对象,也许只需应用atomic就足够了。看原子属性和非原子属性有什么区别?了解更多关于其具体作用的信息。

说实话,我真的不喜欢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包含一个barrier。屏障意味着“当我运行时,不能从此队列中调度其他块”。因此,您有一堆并行运行的读取器块,然后设置器屏障出现并等待所有读取器完成。然后它单独运行,设置值,然后它后面的读者就可以再次并行运行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ARC 避免出现悬空指针 的相关文章

随机推荐