2009-01-10 3 views
3

Lors de la synchronisation de threads en C#, devrais-je également verrouiller un objet lorsque je lis une valeur ou que je la change juste?Faut-il verrouiller les ressources lors de la lecture des valeurs?

par exemple J'ai file d'attente <T> objet. Est-ce que je devrais juste le verrouiller en faisant les Enqueue et Dequeue ou devrais-je également le verrouiller en vérifiant des valeurs comme le compte?

Répondre

3

De MSDN:

Une file d'attente < (de < (T>)>) peut prendre en charge simultanément plusieurs lecteurs , tant que la collection est pas modifiée. Néanmoins, l'énumération à travers une collection n'est intrinsèquement pas une procédure thread-safe . Pour garantir la sécurité des threads lors du dénombrement, vous pouvez verrouiller la collection pendant le dénombrement complet . Pour permettre l'accès à la collection par plusieurs threads pour la lecture et l'écriture, vous devez implémenter votre propre synchronisation .

Vous devez vous assurer qu'aucun lecteur n'est actif pendant la mise en attente d'un élément (un verrou est probablement une bonne idée).

En regardant le compte dans le réflecteur révèle une lecture d'un champ privé. Cela peut être correct en fonction de ce que vous faites avec la valeur. Cela signifie que vous ne devriez pas faire ce genre de choses (sans verrouillage correct):

if(queue.Count > 0) 
    queue.Dequeue(); 
+0

Cela fonctionnerait, cependant, si vous ne partagez pas un verrou pour toutes les lectures, vous obtiendrez de mauvaises performances car un seul thread peut énumérer la collection en même temps temps. –

2

Dépend de ce que vous voulez faire avec le verrouillage. Habituellement, ce type de verrouillage nécessite un mécanisme de verrouillage lecteur/graveur.

Le verrouillage des lecteurs/graveurs signifie que les lecteurs partagent un verrou, de sorte que vous pouvez avoir plusieurs lecteurs lisant la collection simultanément, mais pour écrire, vous devez acquérir un verrou exclusif.

0

Le CLR garantit des lectures atomiques pour des valeurs allant jusqu'à la largeur du processeur. Donc, si vous utilisez 32 bits, la lecture int sera atomique. Si vous utilisez une machine 64 bits, la lecture long sera atomique. Ergo, si Count est un Int32 il n'y a pas besoin de verrouiller.

This post est pertinent à votre question.

+0

La lecture d'un int peut être atomique, mais le calcul du nombre n'est peut-être pas nécessairement atomique. Ce n'est pas juste lire un int. Il nécessite un appel de fonction, parmi probablement d'autres choses. –

+0

Et Count est très probablement une propriété, qui correspond à un appel de fonction implicite. –

+0

Nombre de calculs? D'une propriété? Cela casserait sérieusement mes attentes pour le comportement de la propriété. L'attente (ce qui est correct dans ce cas) est que l'accès à la propriété renvoie simplement la valeur d'un champ. –

1

Si vous ne le verrouillez pas, vous pouvez obtenir une valeur plus ancienne. Une condition de concurrence peut se produire de sorte qu'une opération d'écriture est effectuée en modifiant Count, mais vous obtiendrez la valeur avant la modification. Par exemple, si la file d'attente n'a qu'un seul élément et qu'un thread appelle dequeue, un autre thread peut lire le compte, le trouver toujours 1 et appeler à nouveau dequeue. Le deuxième appel ne sera pas fait jusqu'à ce que le verrou est accordé, mais à ce moment la file d'attente serait réellement vide.

Questions connexes