à l'aide de dispatch_sync dans Grand Central Dispatch
Quelqu'un peut-il expliquer très clairement les cas d'utilisation quel est le but de dispatch_sync
dans GCD
est-ce? Je ne peux pas comprendre où et pourquoi je dois utiliser cette.
Merci!
Vous devez vous connecter pour publier un commentaire.
Vous l'utilisez quand vous voulez exécuter un bloc et d'attendre les résultats.
Un exemple de ceci est le modèle où vous êtes en utilisant un message de la file d'attente au lieu de serrures pour la synchronisation. Par exemple, supposons que vous avez partagé NSMutableArray
a
, avec accès médiée par l'expédition de la file d'attenteq
. Un thread d'arrière-plan peut être l'ajout de la matrice (async), tandis que l'avant-plan de votre fil est en tirant le premier élément (de façon synchrone):dispatch_async
suivie par undispatch_sync
sur la même file d'attente. Cependant, ce modèle est utile lorsque vous voulez lancer simultanément plusieurs emplois sur une autre file d'attente, et puis attendre pour eux tous.dispatch_sync
: créer une nouvelle file d'attente dédiée à votre ressource partagée. À l'intérieur du bloc de passerdispatch_apply
, utilisezdispatch_sync
avec cette file d'attente et l'accès à la ressource partagée à l'intérieur de ce bloc. Vous pouvez utiliser__block
variables si vous avez besoin d'obtenir des données en retour de ce bloc (aussi longtemps que vous êtes prudent de ne pas laisser votre ressource partagée fuite avec elle).-performSelector:onThread:withObject:waitUntilDone:
ouperformSelectorOnMainThread:withObject:waitUntilDone:
et réglagewaitUntilDone
OUI.dispatch_sync
ne peut pas faire ce qu'un verrou peut faire? Si oui, où?D'abord comprendre son frère
dispatch_async
Vous utilisez
dispatch_async
pour créer un nouveau thread. Lorsque vous faites cela, le thread actuel ne s'arrêtera pas. Cela signifie que//Do More Stuff
peut être exécutée avant l'//Do something else
finitionCe qui se passe si vous souhaitez que le thread en cours d'arrêter?
Vous n'utilisez pas d'envoi à tous. Il suffit d'écrire le code normalement
Maintenant, disons que vous voulez faire quelque chose sur un DIFFÉRENTS fil et encore attendre comme si et de s'assurer que les choses ont fait consécutivement.
Il y a beaucoup de raisons de le faire. INTERFACE utilisateur mise à jour, par exemple, est fait sur le thread principal.
C'est là que vous utilisez
dispatch_sync
Ici vous avez obtenu
//Do something
//Do something else
et//Do More stuff
effectué consécutivement même si//Do something else
est fait sur un thread différent.Habituellement, lorsque les gens utilisent thread différent, le but est donc que quelque chose peut exécutée sans attendre. Dites que vous voulez télécharger de gros volumes de données, mais vous voulez garder l'INTERFACE utilisateur lisse.
Donc, dispatch_sync est rarement utilisé. Mais il est là. Personnellement, j'ai jamais utilisé ça. Pourquoi ne pas demander un exemple de code ou un projet qui n'utilise dispatch_sync.
dispatch_sync
est dans une autre asynch processus pour l'utiliser comme un rappel. Par exemple, Données de Base du NSManagedObjectContextperformBlock
méthode peut l'utiliser à la fin du bloc comme un rappel.dispatch_queue_t queue = dispatch_create_queue("com.mydomain.myname.somequeuename", DISPATCH_QUEUE_SERIAL);
et puis vous pouvez l'utiliser pour la synchronisation des trucs comme:dispatch_async(queue, ^{ /* some code for the block */ });
.dispatch_sync()
:__block NSUInteger myValue; dispatch_sync(queue, ^{ myValue = someValueSynced; });
. Si l'écriture, l'utilisationdispatch_async()
et appeler une mise à jour:dispatch_async(queue, ^{ someValueSynced = something; dispatch_async(dispatch_get_main_queue(), ^{ /* update UI, something like tableView reloadData or so */ }); });
(les méthodes de lecture et de mise à jour de l'INTERFACE utilisateur doivent être synchronisés à l'aide dedispatch_sync()
, donc ce doit être thread-safe).dispatch_sync est sémantiquement équivalent à un traditionnel mutex lock.
fonctionne de la même comme
David Gelhar gauche non-dit que son exemple ne fonctionne que parce que tranquillement, il a créé une file série (passé NULL dans dispatch_queue_create ce qui est égal à DISPATCH_QUEUE_SERIAL).
Si vous souhaitez créer simultanées de la file d'attente (pour avoir tous multithread de puissance), son code conduire à des crash à cause de NSArray mutation (addObject:) au cours de mutation (removeObjectAtIndex:) ou même la mauvaise accès (NSArray vont au-delà de limites). Dans ce cas, on devrait utiliser de la barrière afin d'assurer un accès exclusif à la NSArray alors que les deux blocs de l'exécuter. Non seulement il exclut toutes les autres écritures pour le NSArray tandis qu'il court, mais il exclut également tous les autres lectures, la modification coffre-fort.
Exemple simultanées dans la file d'attente devrait ressembler à ceci:
Si vous voulez quelques exemples de l'utilisation pratique de regarder cette question de la mienne:
Comment puis-je résoudre ce blocage qui se produisent occasionnellement?
- Je le résoudre en s'assurant que mon principal managedObjectContext est créé sur le thread principal. Le processus est très rapide et je ne me dérange pas d'attente. Pas d'attente signifie que je vais avoir à traiter avec beaucoup de concurency question.
J'ai besoin de dispatch_sync parce que certains de code doivent être faites sur le thread principal, qui est le thread différent de celui où le code est exécuté.
Donc, fondamentalement, si vous voulez le code de
1. Procéder comme d'habitude. Vous ne voulez pas à vous soucier des conditions de course. Vous voulez vous assurer que le code est terminée avant de passer.
2. Fait sur un thread différent
utilisation dispatch_sync.
Si 1 n'est pas respectée, l'utilisation dispatch_async. Si 2 est violé, il suffit d'écrire le code comme d'habitude.
Jusqu'à présent, j'ai seulement le faire une fois, à savoir quand quelque chose doit être fait sur le thread principal.
Donc voici le code:
dispatch_sync est principalement utilisé à l'intérieur de dispatch_async bloc d'effectuer certaines opérations sur le thread principal(comme la mise à jour de l'interface utilisateur).
Voici un demi-façon réaliste exemple. Vous avez 2000 zip les fichiers que vous souhaitez analyser en parallèle. Mais le zip de la bibliothèque, ce n'est pas thread-safe. Par conséquent, tous les travaux qui touche le zip de la bibliothèque va dans le
unzipQueue
file d'attente. (L'exemple est en Ruby, mais tous les appels directement la carte de la bibliothèque C. "appliquer", par exemple, des cartes à dispatch_apply(3))J'ai utilisé la synchronisation lors de l'expédition à l'intérieur d'un async envoi de signal de l'INTERFACE utilisateur des modifications dans le thread principal.
Mon bloc async retient seulement un peu et je sais que le thread principal est conscient des changements de l'INTERFACE et d'action entre eux. Généralement utilisé dans un bloc de traitement de code qui prend un peu de temps CPU, mais je veux encore l'action de changement de l'INTERFACE à partir de l'intérieur de ce bloc. Concrétiser les changements de l'INTERFACE dans le bloc async est inutile que de l'INTERFACE utilisateur, je crois, s'exécute sur le thread principal. Aussi l'exécution comme secondaire async blocs, ou un délégué, les résultats dans l'INTERFACE utilisateur de ne voir que quelques secondes plus tard et il semble tardy.
Exemple de bloc: