2010-01-22 7 views
6

Pourriez-vous décrire deux méthodes de synchronisation d'accès en écriture multithread effectuées sur un membre de classe?Question d'interview sur .NET Threading

S'il vous plaît quelqu'un pourrait m'aider à savoir ce que cela signifie et quelle est la bonne réponse.

Répondre

13

Lorsque vous modifiez des données en C#, quelque chose qui ressemble à une seule opération peut être compilé en plusieurs instructions. Prenez la classe suivante:

public class Number { 
    private int a = 0; 
    public void Add(int b) { 
     a += b; 
    } 
} 

Lorsque vous construisez, vous obtenez le code IL suivant:

IL_0000: nop 
IL_0001: ldarg.0 
IL_0002: dup 
// Pushes the value of the private variable 'a' onto the stack 
IL_0003: ldfld  int32 Simple.Number::a 
// Pushes the value of the argument 'b' onto the stack 
IL_0008: ldarg.1 
// Adds the top two values of the stack together 
IL_0009: add 
// Sets 'a' to the value on top of the stack 
IL_000a: stfld  int32 Simple.Number::a 
IL_000f: ret 

Maintenant, supposons que vous avez un objet Number et deux threads appellent sa méthode Add comme ceci:

number.Add(2); // Thread 1 
number.Add(3); // Thread 2 

Si vous voulez que le résultat soit 5 (0 + 2 + 3), il y a un problème. Vous ne savez pas quand ces threads vont exécuter leurs instructions. Les deux threads peuvent exécuter IL_0003 (pousser zéro sur la pile) avant soit exécute IL_000a (réellement changer la variable membre) et vous obtenez ceci:

a = 0 + 2; // Thread 1 
a = 0 + 3; // Thread 2 

Le dernier fil pour finir « gagne » et à la fin du processus , a est 2 ou 3 au lieu de 5.

Vous devez donc vous assurer qu'un ensemble complet d'instructions se termine avant l'autre ensemble.Pour ce faire, vous pouvez:

1) Verrouiller l'accès au membre de la classe alors qu'il est en cours d'écriture, en utilisant l'un des nombreux .NET synchronization primitives (comme lock, Mutex, ReaderWriterLockSlim, etc.), de sorte qu'un seul thread peut travailler dessus à la fois.

2) Poussez les opérations d'écriture dans une file d'attente et traitez cette file avec un seul thread. Comme le souligne Thorarin, vous devez toujours synchroniser l'accès à la file d'attente si ce n'est pas sûr pour les threads, mais cela vaut la peine pour les opérations d'écriture complexes.

Il existe d'autres techniques. Certains (comme Interlocked) sont limités à des types de données particuliers, et il y en a encore plus (comme ceux discutés dans Non-blocking synchronization et Part 4 of Joseph Albahari's Threading in C#), bien qu'ils soient plus complexes: approchez-les avec prudence.

+0

+1 pour ReadWriterLockSlim. Cependant, je pense que le PO doit se familiariser davantage avec la programmation multi-thread avant de saisir pleinement ce concept. En ce qui concerne votre deuxième point: vous devrez synchroniser la file d'attente, compliquant simplement votre problème. – Thorarin

+0

Assez vrai, et votre réponse fournit une introduction bien supérieure à ces concepts (bien que j'essaie de prendre un virement différent dans une mise à jour). A propos de la file d'attente, c'est vrai qu'il faut aussi la synchroniser, bien qu'il y ait des cas où cette approche simplifie les choses plutôt que de les compliquer! –

12

Dans les applications multithread, il existe de nombreuses situations dans lesquelles l'accès simultané aux mêmes données peut causer des problèmes. Dans de tels cas, une synchronisation est requise pour garantir qu'un seul thread a accès à la fois.

J'imagine qu'ils signifient utiliser le lock-statement (ou SyncLock dans VB.NET) par rapport à l'aide d'un Monitor.

Vous voudrez peut-être read this page pour des exemples et une compréhension du concept. Cependant, si vous n'avez aucune expérience avec la conception d'applications multithread, il deviendra rapidement évident, si votre nouvel employeur vous met à l'épreuve. C'est un sujet assez compliqué, avec de nombreux pièges possibles tels que deadlock. Il existe également un MSDN page on the subject décent.

Il peut y avoir d'autres options, selon le type de variable membre et la manière dont elle doit être modifiée. Incrémenter un entier par exemple peut être fait avec la méthode Interlocked .Increment. En tant qu'exercice et démonstration du problème, essayez d'écrire une application qui démarre 5 threads simultanés, en incrémentant un compteur partagé d'un million de fois par thread. Le résultat final prévu du compteur serait de 5 millions, mais ce n'est (probablement) pas ce que vous finirez avec :)

Éditer: fait moi-même une implémentation rapide (download). Exemple de sortie:

Unsynchronized counter demo: 
expected counter = 5000000 
actual counter = 4901600 
Time taken (ms) = 67 

Synchronized counter demo: 
expected counter = 5000000 
actual counter = 5000000 
Time taken (ms) = 287 
+0

Merci pour la réponse. J'aimerais en savoir plus sur le multi-threading dans .NET (C#). En fait, j'ai besoin d'en savoir plus sur C# en général cependant. Souhaitez-vous me suggérer un livre qui peut transformer un développeur ordinaire en développeur de prochaine génération. – Supremestar

+0

Aucun titre particulier ne vient à l'esprit, mais je n'utilise pas beaucoup de livres. En fait, c'est assez incroyable que j'ai pré-commandé C# en profondeur, deuxième édition. De bonnes choses, mais il y a probablement des livres plus adaptés à vos besoins. – Thorarin

+2

"C# en profondeur" est un livre génial. –

0

Il existe plusieurs façons, dont plusieurs sont mentionnées précédemment.

  1. ReaderWriterLockSlim est ma méthode préférée. Cela vous donne un type de verrouillage de base de données, et permet la mise à niveau (bien que la syntaxe pour cela soit incorrecte dans le MSDN la dernière fois que j'ai regardé et est très non-évident)
  2. Vous traitez une lecture comme une écriture et empêchez simplement l'accès à la variable
  3. Opérations imbriquées. Cela effectue une opération sur un type de valeur dans une étape atomique. Ceci peut être utilisé pour le filetage sans verrou (vraiment ne recommande pas cela)
  4. mutex et sémaphores (n'ont pas utilisé ces)
  5. déclarations de moniteur (ce qui est essentiellement la façon dont le mot-clé de verrouillage fonctionne)

Bien que je ne veuille pas dénigrer d'autres réponses, je ne ferais confiance à rien qui n'utilise pas l'une de ces techniques. Mes excuses si j'en ai oublié.