5

J'ai une propriété @property NSLock *myLockComment verrouiller un NSLock sur un fil spécifique

Et je veux écrire deux méthodes:

- (void) lock 

et

- (void) unlock 

Ces méthodes verrouillage et de déverrouillage myLock respectivement et ils ont besoin de faire cela indépendamment de ce que le fil ou la file les a appelés. Par exemple, le thread A peut avoir appelé lock mais la file d'attente B peut être celle appelant unlock. Ces deux méthodes doivent fonctionner correctement sans signaler que j'essaie de déverrouiller un verrou à partir d'un autre thread/file d'attente qui l'a verrouillé. De plus, ils doivent le faire de manière synchrone.

Répondre

23

Il est rare que NSLock soit le bon outil pour ce travail. Il y a beaucoup de meilleurs outils maintenant, en particulier avec GCD; plus tard.

Comme vous le savez probablement déjà de the docs, mais je vais le répéter pour ceux qui lisent le long:

Avertissement: La classe NSLock utilise pour mettre en œuvre les threads POSIX 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.

C'est très difficile à implémenter sans interblocage si vous essayez de verrouiller et déverrouiller sur différents threads. Le problème fondamental est que si lock bloque le thread, alors il n'y a aucun moyen pour que le unlock suivant s'exécute sur ce thread, et vous ne pouvez pas unlock sur un thread différent. NSLock n'est pas pour ce problème. Au lieu de NSLock, vous pouvez implémenter les mêmes modèles avec dispatch_semaphore_create(). Ceux-ci peuvent être mis à jour en toute sécurité sur n'importe quel fil que vous aimez. Vous pouvez verrouiller en utilisant dispatch_semaphore_wait() et vous pouvez déverrouiller en utilisant dispatch_semaphore_signal(). Cela dit, ce toujours n'est généralement pas la bonne réponse.

La plupart des conflits de ressources sont mieux gérées avec une file d'attente d'opérations ou une file d'attente de répartition. Ceux-ci fournissent d'excellents moyens de gérer le travail en parallèle, de gérer les ressources, d'attendre les événements, d'implémenter des modèles de producteur/consommateur et de faire presque tout ce que vous auriez fait avec un NSLock ou NSThread auparavant. Je recommande fortement le Concurrency Programming Guide comme une introduction à la façon de concevoir avec des files d'attente plutôt que des verrous.

Questions connexes