Question

J'ai besoin d'un compteur de type long avec les exigences / faits suivants:

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

Sur la base de ces exigences, comment voulez-vous choisir d'implémenter votre compteur? En tant que long simple, comme volatile long ou en utilisant un AtomicLong? Pourquoi?

En ce moment j'ai un volatile long mais se demandait si une autre approche serait mieux. Je suis également incrémentant mon long en faisant ++counter par opposition à counter++. Est-ce vraiment plus efficace (comme je l'ai été amené à croire ailleurs) parce qu'il n'y a pas d'affectation fait?

Était-ce utile?

La solution

Compte tenu de ces ensembles d'exigences, I pense que volatile longue devrait être suffisant. Le compteur ne serait pas incorrect avec un non-volatile long, mais le lecteur peut-être lire des informations périmées dans ce cas.

Un problème est que les lectures et écritures à un long sont pas requis être atomique, par le spécification JVM si elle n'est pas déclarée volatile. Cela voudrait dire que le fil de la lecture pourrait avoir une valeur à peu près si elle lit fictive la valeur alors que le fil d'écriture a mis à jour une partie de la valeur, mais pas l'autre.

La différence entre ++counter et counter++ est probablement non pertinentes, comme 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.

Autres conseils

En Java 8, utilisez LongAdder ce qui est encore mieux que AtomicLong où les conflits de fil est élevé.

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. Sous contention faible mise à jour, les deux classes ont des caractéristiques similaires. Mais sous haute contention, le débit attendu de cette classe est nettement plus élevé, au détriment de la consommation d'espace supérieur.

ce qui est l'exigence de disponibilité de votre programme? Pourriez-vous faire avec un non volatile int et racé-lit?

10 ^ 4 incréments / seconde est une tranche de 100 microseconde. L'efficacité est pas un problème, mais peut-être atomicité. Vous pourriez avoir 2 copies, et quand il est lu, si elles ne sont pas égaux, lire à nouveau.

scroll top