Règles pour rechercher / éviter les données partagées dans une application multithread
-
03-07-2019 - |
Question
Hy,
comme nous le savons tous, développer une application multithreading est une chose difficile. Surtout le moment où et quoi verrouiller n'est pas si évident à mon humble avis. Souvent, je regarde une méthode / classe et je dois me demander si je partage des données, qui peuvent être modifiées par plusieurs threads. Et quand je ne suis pas sûr que cela se termine par un verrou () sur tout un bloc de code.
Ce que je voudrais savoir, par conséquent, est-ce que vous avez des suggestions de modèles / règles, etc. Ou encore des techniques pour vous assurer que votre code est thread-safe.
Exemple:
- Les méthodes statiques ne doivent pas modifier les champs de classe. (Sauf s'ils verrouillent le champ.)
- Les paramètres du type de référence d'une méthode ne doivent pas être passés "directement". Toujours passer un clone.
Au fait:
Microsoft Research travaille sur le ÉCHECS >. Un outil pour trouver et reproduire Heisenbugs dans des programmes concurrents. J'espère que cela et PLINQ permettront d'améliorer le développement des programmes concurrents.
La solution
Dans la mesure du possible, commencez par rendre vos types immuables. Ensuite, il n'y a pas besoin de cloner. Si vous avez besoin de " changer " le contenu d'un objet, faites que la méthode retourne un nouvel objet à la place, comme le font String.Replace
etc.
C’est fondamentalement le style de programmation fonctionnel, et c’est charmant. Il est regrettable que nous n'ayons pas (actuellement) de collections immuables intégrées dans le framework .NET, bien qu'il existe des tiers, dont un de notre propre JaredPar .
Autres conseils
L'encapsulation de données dans une classe est utile pour sécuriser les threads. Vous contrôlez le mode d'accès aux données et vous pouvez rendre la classe responsable de la synchronisation au lieu d'avoir du code dans toute l'application essayant de se synchroniser correctement.
De plus, vous devez placer une variable privée que vous pouvez utiliser comme identifiant de verrou afin d'éviter d'utiliser les données elles-mêmes comme identifiant du verrou. En ayant une variable privée dédiée en tant qu'identificateur de verrou, vous supprimez une source possible d'interblocages.