避免使用ARC悬空指针 [英] Avoid This Dangling Pointer With ARC

查看:75
本文介绍了避免使用ARC悬空指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an object that holds a strong reference to a object:

@property (nonatomic, strong) NSObject *thing;

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

Elsewhere, I have a method that passes the object reference:

[thirdObject doSomething:secondObject.thing];

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

In one case (out of a million or billion), thirdObject ended up working with a dangling pointer, because the object got swapped and had no owner.

我可以通过这样做避免这种情况吗?对于ARC来说是不同的吗?

Can I avoid this by doing this? Is this different for ARC?

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

如果没有,我该如何避免呢?

If not, how can I avoid this?

编辑:消息是发送到已释放实例0x的消息".

Message is "message sent to deallocated instance 0xwhatever"

推荐答案

您必须在不应用某种线程安全性的情况下才能在多个线程上读写属性.现在原则上,对于像字符串这样的简单对象,也许只需应用atomic就足够了.请参阅原子属性和非原子属性之间有什么区别?,详细了解其作用.

You cannot read and write properties on multiple threads without applying some kind of thread-safety. Now in principle, for a simple object like a string, maybe just applying atomic would be enough. See What's the difference between the atomic and nonatomic attributes? for more on exactly what that does.

坦率地说,我真的不太喜欢atomic.我知道它的作用,但这似乎是达到您真正想要的麻烦的方法(并且经常变得比您想要的要少).这不是一个非常通用的解决方案.我无法自定义atomic访问器一点"(例如添加setNeedsDisplay之类).

Frankly, I really don't like atomic very much. I know what it does, but it seems a cumbersome way of getting to what you really want (and often winds up being less than you want). And it's not a very general solution; I can't customize an atomic accessor "a little" (like to add a setNeedsDisplay or the like).

这就是为什么我喜欢基于队列的访问器.他们需要做更多的工作,但是对于许多问题还是有效的.

That's why I like queue-based accessors. They're a little more work, but they're effective for a lot of problems.

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

我喜欢这个系统的地方是,它允许所有需要的读者并行使用.当作家尝试进行更新时,无论涉及多少读者,都可以保证不会饿死.而且它总是很快返回.当值更改时,队列中还有一个明确的点,以便在写者之前请求该值的读者将始终获得旧值,而在写者之后请求该值的读者将始终获得新值,无论存在多少争用在队列中.

What I like about this system is that it allows all the readers as you want in parallel. When a writer tries to make an update, it is guaranteed not to starve, no matter how many readers are involved. And it always returns quickly. There is also a clear point in the queue when the value changes so that readers who requested the value prior to the writer will always get the old value, and readers after the writer will always get the new value, no matter how much contention there is on the queue.

关键是getter是同步的,因此它将等待直到可以获取值,并且setter包含障碍.屏障表示我正在跑步时,无法从此队列中调度其他块".因此,您有一堆并行运行的阅读器块,然后出现了setter障碍,并等待所有阅读器完成.然后,它可以单独运行,设置值,然后它后面的读者可以再次并行运行.

The key is that the getter is synchronous, so it will wait until it can get the value, and the setter includes a barrier. The barrier means "no other blocks may be scheduled from this queue while I am running." So you have a bunch of reader blocks running in parallel, then the setter barrier comes along and waits for all the readers to finish. Then it runs alone, setting the value, and then the readers behind it can run in parallel again.

这篇关于避免使用ARC悬空指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆