2016-08-06 1 views
1

Le code suivant fonctionne sans condition de coursePourquoi est-il possible de mettre à jour simultanément des variables atomiques sans condition de concurrence en Java?

AtomicInteger atomicInt = new AtomicInteger(0); 

ExecutorService executor = Executors.newFixedThreadPool(20); 

IntStream.range(0, 1000) 
    .forEach(i -> executor.submit(atomicInt::incrementAndGet)); 

Voici la mise en œuvre de incrementAndGet

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

On peut voir current n'est pas synchronisé ou fermé à clé, après un thread obtenir le current un autre thread peut déjà mettre à jour le current.

Mais il semble que la classe atomique évite certaines conditions de course.

Quelqu'un peut-il signaler mon erreur?

+0

'compareAndSet()' utilise le verrouillage. Dans la plupart des implémentations, 'compareAndSet()' exécutera une instruction spéciale qui effectue le verrouillage dans le matériel (par exemple, l'instruction CMPXCHG sur le matériel x86.) Https://en.wikipedia.org/wiki/Compare-and-swap –

Répondre

3

compareAndSet définit la valeur (et renvoie true) si et seulement si le premier paramètre est égal à la valeur actuelle de AtomicInteger. C'est-à-dire que si un autre thread avait déjà changé la valeur, alors current ne serait pas égal à la valeur courante, et la boucle serait exécutée une fois de plus.

De l'documentation de compareAndSet(int expect, int update):

atomiquement définit la valeur à la valeur actualisée donnée si la valeur actuelle == la valeur attendue.