web-dev-qa-db-fra.com

Quelles opérations sont atomiques en C #?

Existe-t-il un moyen systématique de savoir si une opération en C # sera atomique ou non? Ou existe-t-il des directives générales ou des règles générales?

49
Eric

Pour quelque chose de plus complet/détaillé:

Les lectures et écritures dans les types de valeurs 32 bits sont atomiques: cela inclut les types de valeurs intrinsèques (struct) suivants: bool, char, byte, sbyte, short, ushort, int, uint, float. Les types suivants (entre autres) ne sont pas garantis atomiques: decimal, double, long, ulong.

par exemple.

int x;
x = 10; // atomic
decimal d;

d = 10m; // not atomic

L'affectation de référence est également une opération atomique:

private String _text;
public void Method(String text)
{
  _text = text; // atomic
}
32
Peter Ritchie

Oui. Lisez la spécification CLI: http://www.ecma-international.org/publications/standards/Ecma-335.htm . Par exemple:

I.12.6.6 Lectures et écritures atomiques

Une CLI conforme garantira que l'accès en lecture et en écriture à des emplacements de mémoire correctement alignés ne dépassant pas la taille du mot natif (la taille du type natif int) est atomique (voir §I.12.6.2) lorsque tous les accès en écriture à un emplacement sont la même taille. Les écritures atomiques ne doivent pas modifier d'autres bits que ceux écrits. À moins qu'un contrôle explicite de la disposition (voir Partition II (Contrôle de la disposition des instances)) soit utilisé pour modifier le comportement par défaut, les éléments de données ne dépassant pas la taille naturelle du mot (la taille d'un int natif) doivent être correctement alignés. Les références d'objets doivent être traitées comme si elles étaient stockées dans la taille native de Word.

[Remarque: Il n'y a aucune garantie sur la mise à jour atomique (lecture-modification-écriture) de la mémoire, à l'exception des méthodes fournies à cet effet dans le cadre de la bibliothèque de classes (voir Partition IV). Une écriture atomique d'un "petit élément de données" (un élément ne dépassant pas la taille native de Word) est nécessaire pour effectuer une lecture/modification/écriture atomique sur du matériel qui ne prend pas en charge les écritures directes sur de petits éléments de données. note de fin]

[Remarque: Il n'y a pas d'accès atomique garanti aux données de 8 octets lorsque la taille d'un int natif est de 32 bits, même si certaines implémentations peuvent effectuer des opérations atomiques lorsque les données sont alignées sur une limite de 8 octets. note de fin]

Concernant la longue question 64 bits, Eric Lippert y répond ici: http://blogs.msdn.com/b/ericlippert/archive/2011/05/31/atomicity-volatility-and-immutability-are- different-part-two.aspx

La spécification CLI offre en fait des garanties plus fortes. La CLI garantit que les lectures et écritures de variables de types de valeur qui sont de la taille (ou plus petite) de la taille du pointeur naturel du processeur sont atomiques; si vous exécutez du code C # sur un système d'exploitation 64 bits dans une version 64 bits du CLR, la lecture et l'écriture des doubles et des entiers longs 64 bits sont également garanties atomiques. Le langage C # ne garantit pas cela, mais la spécification d'exécution le fait. (Si vous exécutez du code C # dans un environnement qui n'est pas implémenté par une implémentation de la CLI, vous ne pouvez bien sûr pas compter sur cette garantie; contactez le fournisseur qui vous a vendu le runtime si vous voulez savoir quelles garanties ils fournissent.)

Un autre point subtil concernant l'accès atomique est que le processeur sous-jacent ne garantit l'atomicité que lorsque la variable en cours de lecture ou d'écriture est associée à un stockage aligné au bon emplacement en mémoire. Finalement, la variable sera implémentée comme un pointeur vers la mémoire quelque part. Sur un système d'exploitation 32 bits, ce pointeur doit être divisible par 4 pour que la lecture ou l'écriture soit garantie atomique, et sur un système d'exploitation 64 bits, il doit être divisible par 8.

29
Chris Shain

D'après les spécifications CLI, vous pouvez obtenir ici :

"Une CLI conforme garantira que l'accès en lecture et en écriture à des emplacements de mémoire correctement alignés ne dépassant pas la taille du mot natif (la taille du type natif int) est atomique ..."

Section 12.5 de la spécification C # ici :

"Les lectures et écritures des types de données suivants doivent être atomiques: bool, char, byte, sbyte, short, ushort, uint, int, float et reference types." Aussi: "... il n'y a aucune garantie de lecture-modification atomique- écrire, comme dans le cas d'une augmentation ou d'une diminution. "

Rendre l'opération d'incrémentation atomique avec this .

6
Secko