Que signifie «atomique» dans la programmation?

276

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 longou double[JLS, 17.4.7].

Que signifie "atomique" dans le contexte de la programmation Java ou de la programmation en général?

James
la source
24
Une opération à la fois.
Subhrajyoti Majumder
1
une seule opération peut être effectuée sur la variable à la fois.
kaysush
1
je soupçonne que les questions de philosophie appartiennent à codereview.stackexchange.com
Phlip
Notant que certaines variables n'ont pas par défaut de lecture et d'écriture atomiques, les déclarant comme volatile longou volatile doublefaisant lire atomique et écrire atomique.
H2ONaCl

Réponses:

372

Voici un exemple, car un exemple est souvent plus clair qu'une longue explication. Supposons qu'il foos'agit d'une variable de type long. L'opération suivante n'est pas une opération atomique:

foo = 65465498L;

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 fooet 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 fooavant 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 :

private volatile long foo;

Ou pour synchroniser chaque accès à la variable:

public synchronized void setFoo(long value) {
    this.foo = value;
}

public synchronized long getFoo() {
    return this.foo;
}
// no other use of foo outside of these two methods, unless also synchronized

Ou pour le remplacer par un AtomicLong:

private AtomicLong foo;
JB Nizet
la source
75
Cela suppose donc qu'il s'exécute dans un système 32 bits. Et si c'était un système 64 bits? Foo = 65465498L; être atomique alors?
Harke
46
@Harke Si vous utilisez Java 64 bits, oui.
Jeroen
4
Est-ce que cela s'applique également à C # et .NET? Si oui, pour obtenir un comportement atomique, le CLR doit être 64 bits?
Fabiano
5
@Fabiano Cela s'applique et voici comment y parvenir dans .NET car nous n'avons pas le mot-clé synchronisé comme Java. stackoverflow.com/questions/541194/…
The Muffin Man
2
Supposons alors que le thread A attribue une valeur longue, puis à mi-chemin le thread B essaie de le lire. Si l'opération A est atomique, alors le thread B attendra qu'il se termine? Cela signifie que les opérations atomiques fourniront une sécurité implicite des threads?
Teoman shipahi
60

"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.

H2ONaCl
la source
25

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:

L'atomicité est une garantie d'isolement des processus concurrents. De plus, les opérations atomiques ont généralement une définition de réussite ou d'échec - elles modifient avec succès l'état du système ou n'ont aucun effet apparent.

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.

Grant Thomas
la source
15

Je viens de trouver un article Atomic vs. Non-Atomic Operations qui m'a été très utile.

"Une opération agissant sur la mémoire partagée est atomique si elle se termine en une seule étape par rapport aux autres threads.

Lorsqu'un stockage atomique est effectué sur une mémoire partagée, aucun autre thread ne peut observer la modification à moitié terminée.

Lorsqu'une charge atomique est effectuée sur une variable partagée, elle lit la valeur entière telle qu'elle est apparue à un instant donné. "

Kurt Zhong
la source
14

Si vous avez plusieurs threads exécutant les méthodes m1 et m2 dans le code ci-dessous:

class SomeClass {
    private int i = 0;

    public void m1() { i = 5; }
    public int m2() { return i; }
}

vous avez la garantie que tout thread appelant m2lira 0 ou 5.

En revanche, avec ce code (où iest un long):

class SomeClass {
    private long i = 0;

    public void m1() { i = 1234567890L; }
    public long m2() { return i; }
}

un thread appelant m2pourrait lire 0, 1234567890L, ou une autre valeur aléatoire car l'instruction i = 1234567890Ln'est pas garantie d'être atomique pour un long(une machine virtuelle Java peut écrire les 32 premiers bits et les 32 derniers bits en deux opérations et un thread peut observer ientre les deux) .

assylias
la source
pourquoi pensez-vous que "long" pose problème alors que "int" ne pose pas de problème? Veuillez voir ici geekswithblogs.net/BlackRabbitCoder/archive/2012/08/09/…
onmyway133
1
Les assignations longues et doubles @entropy ne sont pas garanties atomiques en Java. Vous pouvez donc lire un long où seulement la moitié des bits ont été mis à jour suite à une affectation.
assylias
0

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.

Eugene Shamkin
la source