2009-10-17 7 views
1

Devrais-je créer une seule instance NSLock dans le délégué de l'application, à utiliser par toutes les classes? Ou est-il conseillé de demander à chaque classe d'instancier sa propre instance NSLock si nécessaire?Une instance NSLock doit-elle être "globale"?

Le verrouillage fonctionnerait-il dans le second cas, si par exemple j'avais accès à un contexte d'objet géré qui est réparti sur deux contrôleurs de vue?

+0

Soyez très effrayé lorsque vous utilisez des serrures codées à la main, et méfiez-vous de leur besoin. –

+2

Je ne suis pas sûr de ce que cela signifie. Le guide Données de base suggère de verrouiller l'accès à un contexte d'objet géré si le thread est utilisé. Que pourrais-je utiliser d'autre que pour une paire de verrouillage-déverrouillage 'NSLock' codée à la main? –

+0

Ouais, je disais juste, attention ... dans ce cas, c'est approprié. –

Répondre

3

Si plusieurs objets accèdent à votre objet uniquement pour en lire le contenu, vous n'avez pas du tout besoin de verrou. Si au moins un des objets accède à votre objet pour écrire/mettre à jour son contenu, peu importe si les autres objets accèdent à votre objet pour le lire ou l'écrire/le mettre à jour: dans ce cas, vous avez besoin d'un verrou. Maintenant, afin de protéger correctement votre objet (dans une section de code critique où plusieurs objets peuvent y accéder), vous devez utiliser la même INSTANCE de VERROUILLAGE qui doit être partagée par TOUS les objets possibles accédant à l'objet que vous sont prêts à protéger.

Si votre application a besoin de protéger un objet accessible simultanément par la majorité des classes, alors avoir une seule instance de verrouillage est très bien. Si vous voulez de meilleures performances (surtout si le nombre d'accès simultanés à votre objet est élevé), vous pouvez avoir plusieurs verrous. Chaque verrou sera responsable d'autoriser/refuser l'accès à un attribut/champ spécifique de votre objet. De cette façon, plusieurs objets peuvent accéder à votre objet en changeant simultanément un attribut/champ différent. Vous incrémentez fondamentalement le nombre d'opérations simultanées sur votre objet. Cependant, chaque verrou DOIT TOUJOURS être partagé entre les autres objets qui accèderont à l'objet que vous protégez. Avoir une instance de verrouillage pour chaque contrôleur ne fonctionne tout simplement pas; Cela ne protège PAS votre objet des accès simultanés d'autres objets dans des threads différents. NSLock est implémenté à l'aide de mutex pthread POSIX, il doit donc être utilisé exactement de la même manière. Cela est également clairement indiqué dans la documentation NSLock:

Avertissement: La classe NSLock utilise des threads POSIX pour implémenter son comportement de verrouillage. Lorsque vous envoyez un message de déverrouillage à un objet NSLock, vous devez vous assurer que ce message est envoyé par le même thread qui a envoyé le message de verrouillage initial. Déverrouiller un verrou à partir d'un thread différent peut entraîner un comportement indéfini. Ainsi, afin de préserver la sémantique de la section critique, c'est le même thread qui a acquis le verrou chargé de le relâcher une fois terminé. Notez également que le mécanisme de verrouillage est destiné uniquement aux opérations rapides, c'est-à-dire que vous ne devez acquérir un verrou que pendant une courte période avant de le relâcher. Si vous devez attendre une durée imprévisible, vous avez besoin d'un mécanisme de synchronisation différent, à savoir une variable de condition disponible via la classe NSCondition.

Espérons que cela aide.

+1

Ce qui ressort de la documentation est que le même verrou utilisé pour le verrouillage dans un thread particulier doit également être utilisé pour le déverrouillage. Cependant, il ne ressort pas clairement de la documentation de 'NSLock' que la même instance de verrou doit être utilisée dans toutes les classes. Je lis aussi que si j'utilise '[myLock lock]' plus d'une fois, avant d'émettre un '[myLock unlock]' correspondant, alors le thread va geler. Je suis donc encore incertain si je dois restreindre l'instanciation et la portée de 'myLock' à une classe/thread particulière appelée, ou si je peux utiliser' myLock' à l'échelle de l'application sans problèmes. –

+0

Je suggère de lire la documentation pour les mutex pxpix posix. Vous verrez qu'un mutex (un NSLock) doit être partagé entre tous les threads qui accèderont à l'objet que vous voulez protéger. Notez que je ne dis pas qu'il doit être partagé globalement entre tous les threads: seulement parmi ceux qui accèdent à votre objet. Ce que vous dites à propos du verrouillage deux fois de suite est correct: à moins que le mutex ne soit récursif, un problème apparaîtra. Pour utiliser des mutex récursifs, vous devez utiliser un objet NSRecursiveLock. Voir la documentation "Threading Programming Guide", en particulier la section "Synchronisation". –

1

Vous ne devez pas utiliser de verrous avec des données de base. Cette documentation est probablement périmée. Idéalement, vous devriez avoir un contexte par thread et laisser le contexte gérer le verrouillage de son NSPersistentStoreCoordinator sous-jacent. Ceci est considéré comme seulement façon sûre d'utiliser les données de base dans une application multithread actuellement.

Questions connexes