Dans le livre Effective Java, il indique:
La spécification du langage garantit que la lecture ou l'écriture d'une variable est atomique sauf si la variable est de type
long
oudouble
[JLS, 17.4.7].
Que signifie "atomique" dans le contexte de la programmation Java ou de la programmation en général?
volatile long
ouvolatile double
faisant lire atomique et écrire atomique.Réponses:
Voici un exemple, car un exemple est souvent plus clair qu'une longue explication. Supposons qu'il
foo
s'agit d'une variable de typelong
. L'opération suivante n'est pas une opération atomique:En effet, la variable est écrite en utilisant deux opérations distinctes: une qui écrit les 32 premiers bits, et une seconde qui écrit les 32 derniers bits. Cela signifie qu'un autre thread peut lire la valeur de
foo
et voir l'état intermédiaire.Rendre l'opération atomique consiste à utiliser des mécanismes de synchronisation afin de s'assurer que l'opération est vue, à partir de tout autre thread, comme une seule opération atomique (c'est-à-dire non fractionnable en partie). Cela signifie que tout autre thread, une fois l'opération atomique, verra la valeur de
foo
avant l'affectation ou après l'affectation. Mais jamais la valeur intermédiaire.Une façon simple de le faire est de rendre la variable volatile :
Ou pour synchroniser chaque accès à la variable:
Ou pour le remplacer par un
AtomicLong
:la source
"Opération atomique" signifie une opération qui semble être instantanée du point de vue de tous les autres threads. Vous n'avez pas à vous soucier d'une opération partiellement terminée lorsque la garantie s'applique.
la source
C'est quelque chose qui «apparaît au reste du système comme se produisant instantanément», et relève de la catégorisation de la linéarisation dans les processus informatiques. Pour citer cet article lié plus loin:
Ainsi, par exemple, dans le contexte d'un système de base de données, on peut avoir des `` validations atomiques '', ce qui signifie que vous pouvez pousser un ensemble de modifications de mises à jour vers une base de données relationnelle et ces modifications seront soit toutes soumises, soit aucune d'entre elles dans en cas d'échec, de cette façon les données ne se corrompent pas, et suite aux verrous et / ou files d'attente, la prochaine opération sera une écriture ou une lecture différente, mais seulement après coup . Dans le contexte des variables et du threading, c'est à peu près la même chose, appliqué à la mémoire.
Votre citation souligne que ce comportement ne doit pas être attendu dans tous les cas.
la source
Je viens de trouver un article Atomic vs. Non-Atomic Operations qui m'a été très utile.
la source
Si vous avez plusieurs threads exécutant les méthodes m1 et m2 dans le code ci-dessous:
vous avez la garantie que tout thread appelant
m2
lira 0 ou 5.En revanche, avec ce code (où
i
est un long):un thread appelant
m2
pourrait lire 0, 1234567890L, ou une autre valeur aléatoire car l'instructioni = 1234567890L
n'est pas garantie d'être atomique pour unlong
(une machine virtuelle Java peut écrire les 32 premiers bits et les 32 derniers bits en deux opérations et un thread peut observeri
entre les deux) .la source
En Java, la lecture et l'écriture de champs de tous types sauf long et double se produisent atomiquement, et si le champ est déclaré avec le modificateur volatile, même long et double sont lus et écrits atomiquement. Autrement dit, nous obtenons 100% soit ce qui était là, soit ce qui s'est passé là-bas, ni aucun résultat intermédiaire dans les variables.
la source