Données critiques et threads
Bonjour,
Je souhaiterais avoir vos avis pour l'accès à un objet par plusieurs threads. Cet objet (un NSMutableDictionary) est un cache d'images pouvant être demandé plusieurs centaines de fois par seconde. Il est remplit et lu par 0 ou plusieurs threads. Le tout se déroule donc sur quelques secondes.... c'est pour cette raison que j'ai peur de mettre en place un nslock diminuant les performances. Existe t-il d'autres solutions ?
Merci.
Je souhaiterais avoir vos avis pour l'accès à un objet par plusieurs threads. Cet objet (un NSMutableDictionary) est un cache d'images pouvant être demandé plusieurs centaines de fois par seconde. Il est remplit et lu par 0 ou plusieurs threads. Le tout se déroule donc sur quelques secondes.... c'est pour cette raison que j'ai peur de mettre en place un nslock diminuant les performances. Existe t-il d'autres solutions ?
Merci.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
http://www.objective-cocoa.org/forum/index.php?topic=438.msg4715#msg4715
Il te suffirait par exemple de mettre un accesseur vers ton dictionnaire depuis l'objet que tu définis comme le rootObject (voire le dico lui même). Je ne sais pas ce que ça donne sur le plan thread-safe ceci dit, mais à priori c'est fait pour.
Par exemple si tu écris ton dictionnaire, et après tu commences la session de lectures intensives mais sans écriture.
Si pendant toute la section critique tu n'as que des lectures, il n'y a pas de soucis.
Ce n'est que s'il y a des écritures et des lectures en concurrence que là il faut mettre en place des NSLocks.
En lecture seule ça serait un NSDictionary donc dans ce cas 0 problème.
En fait pour l'histoire j'ai supprimé ce système de threads, je récupère les images plus rapidement et je n'ai plus besoin de threads mis en place au temps où je n'avais pas la fonction speed carbon... (ne sachant pas faire)
aranaud, ce n'est pas fiable à 100%... J'avais déjà un système avec des flags mais par moment l'application restait bloquée (deux threads s'attendant entre eux...)
C'est justement toute la difficulté de ce qu'on appelle la "programmation temps réelle" ou l'utilisation de thread multiples qui se partagent les ressources.
Et c'est à ça que servent les mutex ("mutual-exclusive", pour donner accès à unre ressource de façon exclusive qu'à un thread à la fois) ou les sémaphores et autres trucs du genre (NSLock en Cocoa pour implémenter ce genre de choses si j'ai tout suivi).
En effet avec plusieurs threads le principe c'est que les threads se partagent le temps d'execution, et qu'il se peut très bien par exemple si tu fais une boucle for pour écrire 1000 éléments dans un tableau, qu'en plein milieu de cette boucle d'écriture, le thread soit interrompu par un autre thread qui lui cherchera à lire dans ce tableau... Il pourra alors très bien commencer à lire alors que l'autre thread n'a pas fini d'écrire, et lire des données nouvelles (déjà remplacées) au début et des données anciennes (boucle d'écriture pas encore passée par là ) à la fin, bref faire un joyeux caffouillage entre les anciennes et les nouvelles données, etc...
C'est pour cela qu'il faut protéger ses ressources partagées par plusieurs threads à l'aide de sémaphores ou mutex comme ici.
Pour te donner une idée, on pourrait très bien utiliser un flag à 3 modes "idle","read","write" qui dit dans quel mode on est et dès qu'on thread veut lire, il faut soit que le flag soit idle -- personne n'utilise la ressources -- soit qu'il soir "read" -- d'autres threads utilisent la ressource, mais que pour la lire pas pour la modifier. Si on veut écrire alors là il faut qu'il n'y ait qu'un seul thread à la fois à écrire pour pas qu'ils se marchent dessus, et personne en train de lire (car on pourrait le perturber) donc que le flag soit en "idle".
Mais bon en fait c'est pas aussi simple que ça non plus, donc il faut mieux utiliser les classes comme NSLock & co plutôt que des flags maison.
Et puis il y a aussi le risque de ce qu'on appelle les "deadlocks" aussi, c'est à dire quand 2 threads se bloquent mutuellement. Par exemple une prise de jetons croisés.
exemple :
Donc finalement comme tu le vois, quand on commence à partager des ressources entre plusieurs thread, faut faire attention à plein de petites choses.
C'est aussi pour ça que dans la doc Apple tu as des mentions "thread-safe" et "not thread-safe" parfois. C'est dans les cas où il y a utilisation de ressources partagées et que les mutex/semaphores ont été implémentés ou pas.
Merci.
Je serais fortement tenté en effet de répondre oui, qu'il n'y a aucun risque si tu n'utilise que des objets immutable (enfin que tu te contentes de lectures, quoi).
A une condition bien sûr c'est de ne pas les modifier (dans le sens releaser ton NSDict et le remplacer par un autre) mais ça va de soi.
Mais je préfère :
1) Ne pas dire de conneries (donc mon "oui" est très hésitant, quoi)
2) Te conseiller de mettre des NSLocks quand même, parce que ça ne coute pas grand grand chose finalement de les implémenter dans tes accesseurs.