代码之家  ›  专栏  ›  技术社区  ›  Drux

除非在后台线程中获取新引用,否则可能出现引用计数问题

  •  0
  • Drux  · 技术社区  · 9 年前

    我有一个 second 阅读马库斯·S·扎拉(Marcus S.Zarra)的文章后提出的问题(优秀) Core Data: Data Storage and Management for iOS, OS X, and iCloud (第二版)如果可以的话。

    本书的章节 异步添加NSPersistentStore 包含以下代码(摘录):

    dispatch_queue_t queue;
    queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
    
        // ...
    
        NSPersistentStoreCoordinator *coordinator = nil;
        coordinator = [[self managedObjectContext] persistentStoreCoordinator];
    
        // ...
    });
    

    它还包含以下解释:

    我们获取新引用的原因是 NSPersistentStoreCoordinator 是一个安全问题。如果我们使用 从外部方法引用,我们将增加保留 的计数 NSPersistenStore协调员 并可能导致 不必要的引用计数问题。

    这个潜在的引用计数问题的性质是什么?

    我理解如果调度块将引用 NSPersistenStore协调员 如果范围在外部,它将保留该协调器(将其引用计数增加一),然后只有在块完成执行后才能释放该协调器。如果后台线程从未执行过或者它不会终止,那么引用计数问题仍然存在。

    这就是它的全部吗?或者是否有更微妙的情况也会构成引用计数问题,并可能在这种情况下实现?

    目前,我不会(非常)担心在这种情况下可能出现的引用计数问题(简单的后台操作,它被分派用于立即执行),但可能我遗漏了一些东西。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Matic Oblak    9 年前

    在这个示例中,块本身可以相对晚些时候执行(在这个块之前可以执行很多其他代码)。这意味着上下文或存储协调器可能会发生很多事情,假设在块开始执行之前和之后,存储协调器甚至不是同一个对象。

    通过调用管理器来检索协调器的新引用,您首先确保您将获得最新的协调器,同时保持当前的协调器不从块中删除。如果要从块外部重用协调器,则将保留该协调器,并可能会产生(尽管不太可能)内存膨胀等问题。如果一切都变糟了,块甚至从未被执行过,那么协调器将被永久保留,从而导致内存泄漏。

    这只是一个很好的做法。