3 votes

Ce code est-il Thread-safe ?

Ceci est une version simplifiée de quelques lignes de code que je suis actuellement en train de maintenir :

int SomeFunc() 
{
  const long lIndex = m_lCurrentIndex;
  int nSum = 0;
  nSum += m_someArray[lIndex];
  nSum += m_someArray[lIndex];
  return nSum;
}

lCurrentIndex est mis à jour périodiquement par un autre thread. La question est : est-ce que faire une copie locale de m_CurrentIndex garantit que les deux accès à m_someArray utilisent le même index ?

Veuillez noter qu'il s'agit d'un exemple simplifié ; je réfléchis au concept de faire une copie locale, et non au code exact montré ici. Je sais que le compilateur mettra la valeur dans un registre, mais c'est quand même une copie locale par opposition à lire de l'Index courant deux fois.

Merci !

Édition : L'assignation initiale est sûre, les deux sont garantis d'être sur 32 bits dans notre configuration. Édition2 : Et ils sont correctement alignés sur une frontière de 32 bits (j'avais oublié celui-là)

1voto

Suma Points 11966

Concept de copie locale

Je pense au concept de création d'une copie locale, pas nécessairement le morceau de code exact montré ici.

Cette question ne peut pas être répondue sans en savoir plus. Cela revient à se demander si cette "création d'une copie locale" de m_lCurrentIndex dans l'index lIndex est atomique.

En supposant x86 et en supposant que m_lCurrentIndex est aligné sur DWORD et en supposant que long représente DWORD (ce qui est vrai pour la plupart des compilateurs x86), alors oui, ceci est atomique. En supposant x64 et en supposant que long représente DWORD et m_lCurrentIndex est aligné sur DWORD ou long représente un mot de 64 bits et m_lCurrentIndex est de nouveau aligné sur 64 bits, alors oui, ceci est atomique. Sur d'autres plateformes ou sans la garantie d'alignement, deux lectures physiques ou plus peuvent être nécessaires pour la copie.

Même sans la copie locale étant atomique, vous pouvez toujours la rendre sans verrou et thread safe en utilisant une boucle de style CAS (soyez optimiste et supposez que vous pouvez faire sans verrouillage, après avoir effectué l'opération, vérifiez si tout s'est bien passé, sinon, annulez et réessayez), mais cela peut être beaucoup plus de travail et le résultat sera sans verrou, mais pas sans attente.

Barrières mémoire

Un mot de prudence : une fois que vous avancerez d'un pas, vous serez très probablement en train de manipuler plusieurs variables simultanément, ou de manipuler des variables partagées qui agissent comme des pointeurs ou des indices pour accéder à d'autres variables partagées. À ce stade, les choses deviendront de plus en plus compliquées, car à partir de ce moment, vous devez prendre en compte des éléments comme la réorganisation de la lecture/écriture et les barrières mémoire. Voir aussi Comment puis-je écrire une structure sans verrouillage

0voto

Naveen Points 37095

Oui, il accédera au même élément du tableau. C'est comme si vous preniez un instantané de la valeur de m_lCurrentIndex dans la variable locale. Comme la variable locale a sa propre mémoire, tout ce que vous faites à m_lCurrentIndex n'aura aucun effet sur la variable locale. Cependant, notez que puisque l'opération d'assignation n'est pas garantie d'être atomique, vous pourriez très bien vous retrouver avec une valeur invalide dans l'index l. Cela se produit si vous mettez à jour m_lCurrentIndex à partir d'un thread et en même temps tenter l'assignation dans l'index l à partir de l'autre thread.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X