Question

Disons que j'ai une struct qui se composent de 100 octets. Quelles garanties ai-je obtenu sur le code suivant?

m_myLargeStruct = someValue; // copying 100 bytes
Thread.MemoryBarrier();

// Executed by another thread, after "Thread.MemoryBarrier" was called by the first thread
Console.WriteLine(m_myLargeStruct.ToString());

La garantie de modèle de mémoire que les 100 octets copie sera complète après la mise en place de la barrière de la mémoire? ou ne barrières de mémoire appliquent uniquement pour les types qui sont à la taille de l'architecture du processeur? (4 octets pour 32 bits et 8 octets à 64 bits).
Est-ce la raison pour laquelle la volatile mot-clé valable uniquement pour les types primitifs? (Si je déclare un membre de 8 octets comme volatile, cela signifie qu'un instrinct interverrouillage sera utilisé pour changer sa valeur? [Puisque atomicité n'est pas garanti pour les types de plus de 4 octets sur les machines 32 bits]).

J'espère avoir été assez clair .. :)
Merci

Était-ce utile?

La solution

Il est clair que la réponse est pas , ou plutôt, vous avez aucune garantie sur quoi que ce soit. Rien empêche le système d'exploitation de l'échange sur le fil qui est en train d'écrire à la structure 100 d'octets avant de commencer le fil qui imprime le struct 100 octets.

Une barrière de mémoire est utilisée lorsque vous souhaitez coordonner l'accès aux données par le biais d'un drapeau ou une autre valeur atomique. Je ne sais pas ce que vous essayez de faire exactement, donc je ne peux pas vous donner un bon exemple de code sur la façon dont vous devriez le faire.

Autres conseils

À moins que le fil de la lecture a une trop barrière de mémoire, je ne suis pas penser ça va vous aider beaucoup.

Personnellement, je hésiter à:

  • Structs qui sont ce grand
  • Obtenir profondément dans le modèle de mémoire pour écrire le code sans verrouillage

... sauf si vous avez une raison vraiment important de le faire. Il est énormement difficile d'obtenir un codage sans verrouillage à droite avec les données mutable; Je crois que même les experts luttent. Je trouve généralement que « prendre un lock-out pour chaque bloc accès aux données » approche est plus facile d'obtenir le droit et est très bien en termes de performance pour 99% des cas.

Je confiance à l'équipe de PFX à Microsoft pour obtenir le droit de codage sans verrouillage, et pour eux de me fournir wth façons d'utiliser leur code pour écrire mes propres programmes libres de verrouillage relativement facilement. Je ne me fais pas confiance pour obtenir ce genre de chose à droite. Si jamais je besoin d'utiliser explicitement une barrière de mémoire, cela signifie probablement que je suis en train trop dur.

Vous avez besoin d'une autre barrière de mémoire dans le second fil, avant WriteLine. (Si votre système fournit des barrières de mémoire asymétriques, il suffit d'exécuter une barrière de sortie après la cession et une barrière Acquire avant WriteLine).

Taille de données n'a pas d'importance.

Vous avez besoin d'une barrière de mémoire dans les deux endroits / fils, et bien sûr vous avez besoin d'une sorte de synchronisation entre les deux afin de la 2ème barrière de s fil ne soit pas « run » avant le premier fil.

En particulier, le fil d'écriture a besoin d'une barrière de mémoire « de libération », et le fil de lecture a besoin d'une barrière mémoire « acquièrent » (si la plate-forme sous-jacent supporte la sémantique de barrière séparée).

À moins que vous demandez par curiosité académique ou vous écrivez votre propre cadre, vous devriez vraiment juste utiliser un objet de synchronisation de la bibliothèque / framework / plate-forme. Essayer d'obtenir tout ce genre de choses est correcte délicate, et il est déjà fait dans les objets de synchronisation fournis.

Eh bien, vous ne devriez pas d'abord une struct qui est cette grande. Sauf si vous êtes extrêmement prudent sur la façon dont vous utilisez le struct, il sera plus lent que d'utiliser une classe. Aussi, il est contre-intuitif de la sémantique de la valeur de struct.

Cela dit, la barrière de mémoire garantit que la struct est copiée. L'optimisation ne se déplace pas d'instructions à travers la barrière.

Le mot-clé volatile est un peu différent. Elle garantit qu'aucune opération contre la variable est optimisée loin, et il ne garantit l'ordre des accès mémoire. Cependant, pour les types de données qui ne sont accessibles atomiquement, il est inutile la plupart du temps pour enfiler des fins que vous pouvez toujours lire la moitié d'une nouvelle valeur et la moitié d'une ancienne valeur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top