Est-il nécessaire d'acquérir un verrou sur une variable avant de la lire à partir de plusieurs threads ?
Réponses
Trop de publicités?La réponse courte est : cela dépend.
La réponse est longue :
-
S'il ne s'agit pas d'une valeur partagée, c'est-à-dire qu'un seul thread peut la voir (ou l'utiliser), vous n'avez pas besoin de synchronisation.
-
S'il s'agit d'une valeur immuable, c'est-à-dire que vous ne la définissez qu'une seule fois et que vous ne la lisez qu'ensuite, vous pouvez le faire sans synchronisation (tant que vous ne commencez pas à lire avant que la première écriture ne soit terminée).
-
S'il s'agit d'un type "primitif" d'au plus 32 bits (par ex.
byte
,short
,int
), vous risquez d'obtenir des données périmées (anciennes) lors de la lecture. Si cela ne vous dérange pas, vous êtes prêt. Si les données périmées ne sont pas souhaitables, il suffit de rendre la variablevolatile
peut résoudre ce problème sans synchronisation supplémentaire pour les lectures. Mais si vous avez des écrivains en course, vous devrez suivre les mêmes conseils que pourlong
ci-dessous. -
S'il s'agit d'un type "primitif" de plus de 32 bits (par ex.
long
,decimal
,double
), vous avez besoin d'une synchronisation, sinon vous pourriez lire la "moitié" d'une valeur, la "moitié" d'une autre, et obtenir des résultats farfelus. Pour cela, l'approche recommandée est d'utiliser les méthodes de la classeInterlocked
pour les lectures et les écritures. -
S'il s'agit d'un type de référence, vous aurez besoin d'une synchronisation pour éviter de voir un état invalide (Jeff Lamb's exemple d'image est un bon exemple). Les
lock
pourrait suffire. Là encore, vous devez verrouiller les lectures et les écritures.
Il y a d'autres points à prendre en considération (la durée du verrouillage, par exemple), mais je pense que ces éléments suffisent à répondre à votre question.
Cela dépend du type de variable et de votre plateforme. Par exemple, la lecture des Int64 n'est pas garantie comme étant atomique sur les machines 32 bits. C'est pourquoi, Interlocked.Read
.
Si le chargement de la valeur se fait en une seule instruction d'assemblage, il n'est pas nécessaire d'obtenir un verrou. Vous ne vous souciez pas de savoir si la valeur a changé il y a 10 minutes ou il y a 1 microseconde. Vous voulez juste la valeur maintenant.
Toutefois, si vous chargez un tableau ou une image ENORME, il serait probablement judicieux de le verrouiller. En théorie, vous pouvez être préempté pendant le chargement des données et avoir la moitié du premier élément et la moitié du deuxième élément.
S'il s'agit d'une simple variable, comme un bool ou un int, ce n'est pas nécessaire.
Cela dépend s'il s'agit d'une variable locale ou partagée, et si quelque chose d'autre peut y écrire entre-temps, et ce que vous allez faire après l'avoir lue.
Si vous prenez une décision sur la base de la variable, pensez que la ligne de code suivante peut alors être basée sur des données qui sont désormais périmées.