ios - Coredata 跨线程访问新发现?
大家讲道理
大家讲道理 2017-04-17 17:58:30
0
2
744

最近读了Coredata第一三方库Magical Record作者的一篇文章链接描述,对Coredata访问有了新的疑惑,performBlockAPI 是如何保证线程安全的?

众所周知 , NSManagedObjectContext(简称moc) 是不允许跨线程访问的 ,用人话说就是 在哪个线程创建的moc ,就在哪个线程使用它.

苹果在iOS5.0之后 推出了一个新的 api 操作moc. 有代码长这样 :

__block BOOL savedOK = NO;
[myMOC performBlock:^{
    // Do lots of things with the context.
    savedOK = [myMOC save:&error];
}];

即是通过NSPrivateQueueConcurrencyType类型创建的MOC 系统会为其分配一个私有队列,而不需要我们手动为它创建线程, 从此并发变的更容易 。

但是通过上面那篇文章, Magical Record 作者指出, 苹果的新api 使用了GCD , 而在GCD中的并发我们是通过队列来实现的,即我们只关注和操作队列,而不是直接操作线程。 当你提交一个block代码块到GCD的队列上,队列会自动分配线程去执行这个block。 但是,GCD不能保证这个队列始终在一条线程运行!! 也就是说,当你提交block到队列时,是将任务放到线程A执行,但下一刻,也许任务已经不在线程A而在线程B了!虽然此时依旧在同一个队列!这即是作者弃用contextForCurrentThread
的原因。

那么问题来了,如上文代码中,myMOC是一个NSPrivateQueueConcurrencyType类型的上下文,创建时系统为其分配了私有队列Q,我们假设myMOC创建发生在线程A,线程A属于队列Q,但由于GCD的特性,某一刻将block任务分配到了属于队列Q的线程B ,也就是说,此时,创建于线程A的myMOC 可能会在线程B被访问 , 这就发生了跨线程访问!

这又如何解释呢? 希望对这部分了解的大虾给予解答,如果我解决了这个问题,也会在楼下贴出 。

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

répondre à tous(2)
Ty80

Merci beaucoup pour votre réponse. Mais il semble y avoir deux autres questions :

1. L'article de l'auteur ne dit pas directement "La nouvelle API d'Apple utilise GCD". Il y a une phrase dans l'article original However, now, as more of you (and the heart of MagicalRecord) is using GCD, Cela signifie que le noyau de MagicalRecord utilise GCD, mais j'ai parcouru le code source de MagicalRecord et il semble que je n'ai pas trouvé que la file d'attente de planification GCD est utilisée pour implémenter des opérations asynchrones. Le noyau utilise performBlock et performBlockAndWait pour implémenter. opérations asynchrones sur MOC. .Donc je suppose que ce que l'auteur veut dire, c'est que performBlock sera lié à GCD Sinon, pourquoi GCD n'est-il pas utilisé, mais l'interface précédente est abandonnée à cause des caractéristiques de GCD ? Et contextForCurrentThread ?

2. Mis à part la question 1, une partie de la documentation d'Apple dit ceci :

The NSPrivateQueueConcurrencyType configuration creates its own queue upon initialization and can be used only on that queue. Because the queue is private and internal to the NSManagedObjectContext instance, it can only be accessed through the performBlock: and the performBlockAndWait: methods.
Un MOC de type NSPrivateQueueConcurrencyType créera sa propre file d'attente lors de l'initialisation. Cette file d'attente est privée au sein de ce MOC. Cela peut donc être compris comme :

J'ai créé un MOC de
dans le fil a, qui créera une file d'attente privée et gérera le contenu sous NSPrivateQueueConcurrencyType dans le fil b.performBlock

若有代码:

  NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [moc performBlock:^{
        // ... do things
        NSError *error;
        [moc save:&error];
    }];
    
Si le contexte est créé dans le thread a, alors il doit appartenir au thread a, mais il est accessible dans le thread b de la file d'attente ? N'est-ce pas un accès cross-thread ?

Est-ce que

entre en conflit avec

qui garantit l'exécution dans le thread auquel appartient le contexte actuel ? Comment est-ce garanti ? Est-ce que b et a sont le même thread lors de la création d’une file d’attente privée ? Comment faire ?performBlock

PHPzhong

J'ai lu l'article auquel vous avez lié : "Mais à travers l'article ci-dessus, l'auteur de Magical Record a souligné que la nouvelle API d'Apple utilise GCD et que nous implémentons la concurrence dans GCD via des files d'attente." votre phrase ci-dessus indiquant que "la nouvelle API d'Apple utilise GCD".

Ce qui suit est le document Apple référencé. La méthode performBlock garantira qu'elle est exécutée dans le thread auquel appartient le contexte actuel :

performBlock: and performBlockAndWait: ensure the block operations are executed on the queue specified for the context. The performBlock: method returns immediately and the context executes the block methods on its own thread. With the performBlockAndWait: method, the context still executes the block methods on its own thread, but the method doesn’t return until the block is executed.
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal