27 votes

La double lecture est-elle atomique sur une architecture Intel?

Mon collègue et moi avons un argument sur l'atomicité de la lecture d'un double sur une architecture Intel à l'aide de C# .NET 4.0. Il fait valoir que nous devrions utiliser Interlocked.Exchange méthode pour l'écriture en double, mais il suffit de lire la double valeur (dans un autre thread) est garanti d'être atomique. Mon argument est que .NET n'est pas le garantir l'atomicité, mais son argument est que sur une architecture Intel, c'est garanti (peut-être pas sur AMD, SPARC, etc.).

Intel et .NET experts de partager quelques lumières sur ce point?

Lecteur est OK pour lire un rassis (précédente) de la valeur, mais pas de valeur incorrecte (lecture partielle avant et après l'écriture de donner une valeur d'ordures).

22voto

Eric Lippert Points 300275

Mon collègue et moi avons un argument sur l'atomicité de la lecture d'un double sur une architecture Intel à l'aide de C# .NET 4.0.

Intel garantit que 8 octets, les chambres doubles sont atomiques à lire et à écrire lors de l'alignement de 8 octets limite.

C# n'a pas de garantie qu'un double est alignée sur une frontière d'octet 8.

Il fait valoir que nous devrions utiliser Interlocked.Exchange méthode pour écrire en un double, mais il suffit de lire la double valeur (dans un autre thread) est garanti d'être atomique.

Votre collègue ne pense pas à ce travers. Interloqué opérations sont seulement atomique à l'égard des autres opérations verrouillées. Il ne fait aucun sens d'utiliser opérations verrouillées certains de l'époque; c'est comme dire que le trafic qui passe par l'intersection vers le nord n'a pas à obéir à la circulation de la lumière, parce que le trafic qui passe par l'intersection de l'ouest n' obéir à la circulation de la lumière. Tout le monde doit respecter les lumières afin d'éviter les collisions; vous ne pouvez pas faire juste la moitié.

Mon argument est que .NET n'est pas le garantir l'atomicité, mais son argument est que sur une architecture Intel, c'est garanti (peut-être pas sur AMD, SPARC, etc.).

Regardez, supposons que cet argument était correcte, il ne l'est pas. C'est la conclusion que nous sommes censés arriver ici, est que les plusieurs nanosecondes qui est enregistré par faire le mal sont en quelque sorte en vaut le risque? Oublier interloqué. Prendre un verrouillage complet à chaque fois. Le seul moment où vous devriez pas prendre un verrouillage complet lors du partage de la mémoire entre les threads, c'est quand vous avez démontré un problème de performance qui est effectivement dû à la période de douze nanoseconde généraux de la serrure. C'est lors de l'un des douze nanoseconde pénalité est la plus lente chose dans votre programme et qui est toujours inacceptable, c'est le jour où vous devriez envisager d'utiliser un bas de solutions de verrouillage. Est le plus lent chose dans votre programme de prendre un 12 de l'ordre de la nanoseconde uncontended serrure? Non? Alors arrêter d'avoir cet argument, et de dépenser votre précieux temps à fabriquer les pièces de votre programme de prendre plus de 12 nanosecondes plus rapide.

Lecteur est OK pour lire un rassis (précédente) de la valeur, mais pas de valeur incorrecte (lecture partielle avant et après l'écriture de donner une valeur d'ordures).

Ne pas confondre l'atomicité de volatilité.

Les opérations verrouillées, et le verrouillage de l'énoncé, à la fois établir une barrière de mémoire, qui garantit que le up-to-date de valeur est en lecture ou publié. Ordinaire non-volatile de lecture ou d'écriture n'est pas nécessaire de le faire; si elle arrive à le faire, tu as de la chance.

Si ces questions vous intéressent, une question que je me suis parfois demandé à ce sujet est dans quelles circonstances un verrou autour d'un nombre entier d'accès peuvent être gommés. Mes articles sur le sujet sont:

20voto

codenheim Points 6836

Oui et non. Sur les processeurs 32 bits, il n'est pas garanti atomique, parce que double est plus grand que le natif de wordsize. Sur un processeur 64 bits à aligner correctement l'accès est atomique. Le 64 bits CLI garantit tout sur un 64-bit lire comme atomique. Donc, vous devez construire votre assemblée pour x64 (pas n'Importe quel CPU). Sinon, si votre assemblée peut être exécuté sur 32 bits, vous feriez mieux d'utiliser Interloqué, voir l'Atomicité, la volatilité et l'immutabilité sont différents, partie deux par Eric Lippert. Je pense que vous pouvez compter sur Eric Lippert la connaissance de l'environnement Microsoft CLR.

Le standard ECMA CLI prend également en charge ce, même si C# elle-même ne garantit pas:

Conforme de la CLI doit garantir que l'accès en lecture et écriture aligner correctement les emplacements de la mémoire qui n'est pas plus que le natif de la taille de mot (la taille du type native int) est atomique (voir §I. 12.6.2)

Il dit aussi que sur les processeurs, où les opérations sont atomiques, Interloqué méthodes sont souvent compilées en une seule instruction, donc, dans mon livre il n'y a pas de perte de performance dans l'utilisation des ti. D'autre part, il peut y avoir une aggravation de la peine de ne pas l'utiliser quand vous devriez.

Un autre Débordement de Pile question est Ce que les opérations sont atomiques en C#?.

18voto

Anders Abel Points 36203

De la lecture ou de l'écriture d'un double est atomique sur une architecture Intel si ils sont alignés sur une 8 octets de l'adresse de la frontière. Voir la mise à Jour Est double opération atomique.

Même si les lectures et écritures de doubles pourraient effectivement être atomique en .NET code sur une architecture Intel, je n'aurais pas confiance en elle que le C# spec n'est pas garantie, consultez cette citation d'une Réponse par Eric Lippert.

Lit et écrit des types de données suivants sont atomiques: bool, char, octet, sbyte, short, ushort, uint, int, float, et les types référence. Dans outre, les lectures et les écritures des types enum avec un type sous-jacent dans la liste précédente sont également atomique. Lit et écrit les autres types, y compris de long, ulong, double, decimal, ainsi que définis par l'utilisateur les types ne sont pas garantis pour être atomique.

Utiliser Interlocked pour la lecture et l'écriture pour être sûr. Il garantit l'atomicité. Sur une architecture où il est atomique par défaut, il ne devrait pas générer de frais généraux. Vous devez utiliser Interlocked pour la lecture de l'écriture pour s'assurer qu'aucun partiellement écrite, les valeurs sont lues (citation d' InterLocked.Read() de la documentation):

La méthode de Lecture et 64 bits des surcharges de l'Incrémentation, Décrémentation, et d'Ajouter méthodes sont vraiment atomique uniquement sur les systèmes sur lesquels un Système.IntPtr est 64 bits. Sur d'autres systèmes, ces méthodes sont atomiques avec égard les uns des autres, mais pas à l'égard d'autres moyens de l'accès aux données. Ainsi, pour être thread-safe sur les systèmes 32 bits, tout l'accès à une valeur de 64 bits doivent être faites par les membres de la Classe Interlocked.

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