Bonne façon d'utiliser SyncLock (en général)
C'est un suivi à un question précédente concernant le verrouillage de deux List(Of T) des objets. La réponse a été utile, mais m'a laissé avec une autre question.
Supposons que j'ai une fonction comme ceci:
Public Function ListWork() As Integer
List1.Clear()
..Some other work which does not modify List1..
List1.AddRange(SomeArray)
..Some more work that does not involve List1..
Return List1.Count
End Function
qui réside dans une classe qui déclare List1. Dans un environnement multithread, je comprends maintenant que je devrais avoir une privé de verrouillage d'un objet pour la liste 1 et de verrouillage List1 à chaque fois qu'il est modifié ou énumérés. Ma question est, dois-je faire ceci:
Private List1Lock As New Object
Public Function ListWork() As Integer
SyncLock List1Lock
List1.Clear()
End SyncLock
..Some other work which does not modify List1..
SyncLock List1Lock
List1.AddRange(SomeArray)
End SyncLock
..Some more work that does not involve List1..
SyncLock List1Lock
Dim list1Count As Integer = List1.Count
End SyncLock
Return list1Count
End Function
ou ceci:
Private List1Lock As New Object
Public Function ListWork() As Integer
SyncLock List1Lock
List1.Clear()
..Some other work which does not modify List1..
List1.AddRange(SomeArray)
..Some more work that does not involve List1..
Dim list1Count As Integer = List1.Count
End SyncLock
Return list1Count
End Function
Je suppose que l'exemple précédent est-elle optimale?
Vous devez vous connecter pour publier un commentaire.
À partir de ces exemples, il est difficile de dire laquelle est la bonne, si l'un des deux est. Quelques recommandations/observations mais qui pourrait vous aider à répondre à votre question, ou de savoir quoi offrir pour plus d'informations:
Tout d'abord, avez-vous de synchroniser? Serait-il plus logique pour chaque thread avoir une instance de cette classe? Si chaque instance locale pour le thread, et n'est que modifié et utilisé sur ce thread, vous n'avez pas besoin de verrouillage.
Si le but de cette classe et en utilisant des threads est pour le traitement en parallèle d'un ensemble de données plus important, il pourrait faire plus de sens pour le thread principal pour se répartir la tâche en quelque manière logique, et puis d'attendre pour les threads de travail complète. Dans ce cas, au lieu de gérer des threads sur votre propre, regarder dans la ThreadPool et d'attendre les poignées. La plupart du sale boulot est fait pour vous alors.
Sur la synchronisation/verrouillage en général: Si l'opération a été interrompue entre les étapes, les données cohérente/valide?
Dans votre exemple, disons que vous avez deux fils. La première est dans la zone entre
.AddRange()
et.Count
, lors de la deuxième thread vient entre la fonction, et acquiert le verrou sur la liste.1 Thread s'exécute un peu plus, et frappe le verrouillage de garder le
.Count
méthode, et va se coucher. Thread 2 dans le temps efface la liste, puis libère le verrou, se réveille le Thread 1, qui acquiert la serrure.Dans ce cas, le Thread 1 sera retourné 0 de cette fonction, lorsque le travail a été fait par le thread 1 pour créer la liste. Et puis, la liste de longueur ne sera pas vraiment 0, depuis le thread 2 a venir le long et a rempli la liste.
Dans ce cas, les verrous autour de la personne de la liste des opérations pause le programme, de sorte qu'il est plus logique d'avoir une serrure environs, entre
Clear
et laCount
appel.En bref, le multi-threading est une bonne façon de présenter l'ensemble de la classe de bogues relatifs à Des Conditions De Course, qui souvent résultat en Heisenbugs.
Il est souvent judicieux d'éviter les fils quand vous le pouvez. Si vous ne pouvez pas, essayez d'organiser votre charge de travail dans les moyens qui nécessitent un minimum de synchronisation (par exemple le fil d'un ensemble de données au début, puis l'attente du signal d'achèvement, comme avec le pool de threads exemple lié). Si vous ne pouvez pas le faire, puis de la bande de roulement soigneusement, et demandez-vous toujours "Que se passerait-il si deux threads s'exécutent dans ce domaine".
J'espère que cela aide les bras vous pour de futures aventures dans le code multithread.
"Ça dépend". Les deux exemples qui ont des sémantiques différentes.
Dans ce dernier exemple, le ensemble des opérations est atomique à l'égard de la serrure. Alors que dans l'exemple précédent de l'accès à la liste est gardée dans la serrure, mais l'ensemble des opérations ne peut pas être correctement perçu comme atomique (à l'égard de la serrure).
Imaginer ce qui pourrait/qui pourrait arriver en termes de fonctionnement/thread entrelacement si
ListWork
a été invoqué sur le même objet par différents threads.Heureux de codage.