Domanda

Ho bisogno di un contatore di tipo long con i seguenti requisiti/fatti:

  • L'incremento del contatore dovrebbe richiedere il minor tempo possibile.
  • Il contatore verrà scritto solo da un thread.
  • La lettura dal contatore verrà effettuata in un altro thread.
  • Il contatore verrà incrementato regolarmente (fino a qualche migliaio di volte al secondo), ma verrà letto solo una volta ogni cinque secondi.
  • La precisione precisa non è essenziale, è sufficiente solo un'idea approssimativa delle dimensioni del contatore.
  • Il contatore non viene mai azzerato, né decrementato.

Sulla base di questi requisiti, come sceglieresti di implementare il tuo contatore?Come semplice long, come un volatile long o utilizzando un AtomicLong?Perché?

Al momento ho un volatile long ma mi chiedevo se un altro approccio sarebbe stato migliore.Sto anche incrementando il mio long facendo ++counter al contrario di counter++.È davvero più efficiente (come mi è stato portato a credere altrove) perché non viene svolto alcun incarico?

È stato utile?

Soluzione

Considerati questi requisiti, I pensare Che un volatile lungo dovrebbe essere sufficiente.Il contatore non sarebbe errato con un non-volatile lungo, ma in questo caso il lettore potrebbe leggere informazioni obsolete.

Un problema è che legge e scrive su a long Sono non necessario essere atomico, dal Specifica JVM se non è dichiarato volatile.Ciò significherebbe che il thread di lettura potrebbe ottenere un valore praticamente fittizio se legge il valore mentre il thread di scrittura ha aggiornato una parte del valore, ma non l'altra.

La differenza tra ++counter E counter++ È probabilmente irrilevante, poiché la JVM si renderà conto che il valore dell'espressione non viene più utilizzato e in questo caso i due sono equivalenti.

Altri suggerimenti

In Java 8, utilizzare LongAdder che è anche meglio di AtomicLong dove filetto contesa è elevata.

LongAdder JavaDoc:

  

Questa classe è generalmente preferibile AtomicLong quando più thread aggiornare una somma comune che viene utilizzato per scopi quali la raccolta dei dati, non per controllo di sincronizzazione a grana fine. Sotto bassa contesa aggiornamento, le due classi hanno caratteristiche simili. Ma sotto alta contesa, il throughput atteso di questa classe è significativamente più alto, a scapito di una maggiore consumo di spazio.

qual è il requisito di uptime per il vostro programma? Potrebbe accontentarsi di una non-volatili int e filante-legge?

10 ^ 4 incrementi / secondo è 1 ogni 100 usec. L'efficienza non è un problema, ma potrebbe essere atomicità. Si potrebbe avere 2 copie di esso, e quando si legge, se non sono uguali, leggere di nuovo.

parla dei possibili modi per implementare un contatore Credo che questa implementazione dovrebbe funzionare per voi

class LessNaiveVolatieIdGenerator {
private static volatile long id = 0;
public static long nextId() {
    long nextId = (id = id + 1); // or nextId = id++;
    return nextId;
}

}

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top