web-dev-qa-db-fra.com

AtomicInteger.incrementAndGet () contre AtomicInteger.getAndIncrement ()

Lorsque la valeur de retour n'est pas intéressante, existe-t-il une différence (même non pertinente dans la pratique) entre les méthodes AtomicInteger.getAndIncrement() et AtomicInteger.incrementAndGet() , lorsque la valeur de retour est ignorée?

Je pense à des différences telles que celles qui seraient plus idiomatiques, et qui mettraient moins de charge dans les caches CPU à synchroniser, ou quoi que ce soit vraiment, n'importe quoi pour aider à décider lequel utiliser de manière plus rationnelle que de lancer une pièce.

39
hyde

Puisqu'aucune réponse à la question réelle n'a été donnée, voici mon opinion personnelle basée sur les autres réponses (merci, vote positif) et Java:

incrementAndGet()

est préférable, car les noms de méthode doivent commencer par le verbe décrivant l'action, et l'action prévue ici consiste à incrémenter uniquement.

Commencer par le verbe est la convention commune Java, également décrite par les documents officiels:

"Les méthodes doivent être des verbes, en cas de mélange avec la première lettre en minuscule, avec la première lettre de chaque mot interne en majuscule."

26
hyde

Le code est essentiellement le même, donc peu importe:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}
29
assylias

Non, il n'y a pas de différence (si vous ne vous souciez pas de la valeur de retour).

Le code de ces méthodes (dans l'OpenJDK) diffère seulement en ce que l'on utilise return next et les autres utilisations return current.

Les deux utilisent compareAndSet sous le capot avec exactement le même algorithme. Les deux doivent savoir à la fois l'ancienne et la nouvelle valeur.

9
Joachim Sauer

Je veux juste ajouter aux réponses existantes: il pourrait y avoir une très petite différence non perceptible.

Si vous regardez cette implémentation :

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

Remarque - les deux fonctions appellent exactement la même fonction getAndAddInt, sauf +1 part, ce qui signifie que dans cette implémentation getAndIncrement est plus rapide.

Mais, voici ancienne implémentation :

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

La seule différence est la variable de retour, donc les deux fonctions exécutent exactement la même chose.

5
Iłya Bursov

Ici, je donne un exemple. J'espère que cela effacera votre doute.

Supposons que j'ai une variable i comme

AtomicInteger i = new AtomicInteger ();

Dans ce cas:

i.getAndIncrement () <==> i ++;

Et

i.incrementAndGet () <==> ++ i;

Veuillez consulter les programmes ci-dessous

public class Test1
{   
    public static void main(String[] args) 
    {               
        AtomicInteger i = new AtomicInteger();
        System.out.println(i.incrementAndGet());  
        System.out.println(i);  

    }

}

**production

1 1 ====================================== **

public class Test2
{   
    public static void main(String[] args) 
    {               
        AtomicInteger i = new AtomicInteger();
        System.out.println(i.getAndIncrement());  
        System.out.println(i); 

    }

}

**production

0 1 ------------- **

Commentaire: 1) Dans la classe Test1, incrementAndGet () va d'abord incrémenter la valeur i puis imprimer.

2) Dans la classe Test2, getAndIncrement () affichera d'abord la valeur i puis incrémentera.

C'est tout.

0
Ajju_bhai