2015-09-17 22 views
7

AtomicInteger funziona con due concetti: CAS e variabile volatile.Come funziona "Confronta e imposta" in AtomicInteger funziona

Utilizzando la variabile volatile, il valore corrente sarà visibile a tutti i thread e non verrà memorizzato nella cache.

Ma io sono confuso su CAS (confrontare e set) concetto che è spiegato qui di seguito:

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

La mia domanda è che cosa if(compareAndSet(current, next) rendimenti false? Il valore non sarà aggiornato? In questo caso che cosa accadrà quando un thread è in esecuzione il caso qui di seguito:

private AtomicInteger count = new AtomicInteger(); 
count.incrementAndGet(); 
+0

http://blog.slaks.net/2013-07-22/thread-safe-data-structures/ – SLaks

risposta

10

Gli oggetti atomici utilizzano Compare and Swap meccanismo per renderli atomico - cioè è possibile garantire che il valore era come specificato ed è ora al nuovo valore.

Il codice che hai postato cerca continuamente di impostare il valore corrente su un valore in più rispetto a prima. Ricorda che un altro thread potrebbe aver eseguito anche un get e sta provando a impostarlo anch'esso. Se due thread si incrociano l'un l'altro per modificare il valore, è possibile che uno degli incrementi non riesca.

Si consideri il seguente scenario:

  1. Discussione 1 chiamate get e ottiene il valore 1.
  2. Il thread 1 calcola next in 2.
  3. Thread 2 chiama get e ottiene il valore 1.
  4. Thread 2 calcola next per essere 2.
  5. Entrambi i thread cercano di scrivere il valore.

Ora, a causa di Atomics - solo thread riuscirà, l'altro sarà ricevere false dal compareAndSet e andare in giro di nuovo.

Se questo meccanismo non è stato utilizzato, sarebbe possibile che entrambi i thread incrementassero il valore risultando in realtà solo un incremento effettivamente eseguito.

Il loop infinito confuso for(;;) si interrompe solo se molti thread scrivono sulla variabile contemporaneamente. Sotto carichi molto pesanti potrebbe girare più volte, ma dovrebbe completarsi abbastanza rapidamente.

5

for (;;) è un ciclo infinito, quindi sarà solo ripetere il tentativo.