2010-03-15 7 views
17

J'ai besoin d'un compteur de type long avec les exigences/faits suivants:Long primitif ou AtomicLong pour un compteur?

  • incrémenter le compteur devrait prendre aussi peu de temps que possible.
  • Le compteur ne sera écrit que par un thread.
  • La lecture à partir du compteur se fera dans un autre thread.
  • Le compteur sera incrémenté régulièrement (jusqu'à quelques milliers de fois par seconde), mais ne sera lu qu'une fois toutes les cinq secondes.
  • Une précision précise n'est pas essentielle, seule une idée approximative de la taille du compteur est suffisante.
  • Le compteur n'est jamais effacé, décrémenté.

En fonction de ces exigences, comment choisiriez-vous d'implémenter votre compteur? En tant que simple long, en tant que volatile long ou en utilisant un AtomicLong? Pourquoi?

En ce moment j'ai un volatile long mais je me demandais si une autre approche serait meilleure. J'augmente aussi mon long en faisant ++counter par opposition à counter++. Est-ce vraiment plus efficace (comme on me l'a laissé croire ailleurs) parce qu'il n'y a pas de mission en cours?

Merci à l'avance

Rich

+0

volatile devrait être bon, car le contrat stipule que chaque lecture sur une variable volatile vient après la libération de verrouillage d'une écriture précédente. – fasseg

+0

Si vous ne le mettez à jour que quelques milliers de fois par seconde et que vous utilisez un processeur non intégré, la différence n'est pas importante; vous pouvez faire des millions de mises à jour de 'AtomicLong' par seconde sur la plupart des machines de nos jours. Pourtant, je suis d'accord que «volatile» devrait être suffisant. Vous pouvez encoder les deux à la fois et vérifier à quelle fréquence ils correspondent (et quand ils ne le font pas à quelle distance ils sont) si vous voulez être sûr. –

+0

@Riduidel nous comptons les paquets entrants de données, et je ne nous soucions pas vraiment si le nombre est 12,345,678 ou s'il est légèrement en retard à 12,345,602 – Rich

Répondre

11

Compte tenu de ces ensembles d'exigences, je pense qu'une longue volatile devrait être suffisant. Le compteur ne serait pas incorrect avec une longueur de volatile, mais le lecteur pourrait lire des informations obsolètes dans ce cas.

Un problème est que lit et écrit à un long sont not required to be atomic, par le JVM specification si elle est pas déclarée volatile. Cela signifierait que le thread de lecture pourrait obtenir une valeur assez fictive s'il lit la valeur alors que le thread d'écriture a mis à jour une partie de la valeur, mais pas l'autre.

La différence entre ++counter et counter++ est probablement hors de propos, que la machine virtuelle Java se rendra compte que la valeur de l'expression n'est pas utilisé plus et les deux sont équivalents dans ce cas.

0

Quelle est la durée de disponibilité de votre programme? Pourriez-vous vous contenter d'un int non-volatile et de lectures-racistes?

+0

Uptime est aussi long que possible - cela fonctionne dans un serveur. – Rich

0

10^4 incréments/seconde est 1 toutes les 100 usec. L'efficacité n'est pas un problème, mais l'atomicité pourrait l'être. Vous pourriez en avoir 2 copies, et quand elle est lue, si elles ne sont pas égales, relisez.

0

Ce article parle des moyens possibles pour mettre en œuvre un compteur Je pense que cette mise en œuvre devrait fonctionner pour vous

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

}

4

En Java 8, utilisez LongAdder ce qui est encore mieux que AtomicLong où fil la contention est haute.

LongAdder JavaDoc:

Cette classe est habituellement préférable de AtomicLong lorsque plusieurs threads sont mis à jour une somme courante qui est utilisée à des fins telles que la collecte de statistiques, et non pas pour le contrôle de la synchronisation fine. En cas de conflit de mise à jour faible, les deux classes ont des caractéristiques similaires. Mais sous haute contention, le débit attendu de cette classe est significativement plus élevé, au détriment de l'augmentation de la consommation d'espace.

+0

La contention n'est pas élevée. Un seul thread écrira dessus. –

Questions connexes