Frage

Ich brauche einen Schalter vom Typ long mit den folgenden Anforderungen/Fakten:

  • Das Inkrementieren des Zählers sollte so wenig Zeit wie möglich dauern.
  • Der Zähler wird nur von einem Thread geschrieben.
  • Das Lesen aus der Theke erfolgt in einem anderen Thread.
  • Der Zähler wird regelmäßig inkrementiert (bis zu ein paar tausendmal pro Sekunde), aber nur alle fünf Sekunden gelesen.
  • Genauige Genauigkeit ist nicht wesentlich, nur eine grobe Vorstellung von der Größe des Zählers ist gut genug.
  • Der Zähler wird niemals gelöscht, abgeschlossen.

Wie würden Sie basierend auf diesen Anforderungen Ihren Zähler implementieren? Als einfach long, Als ein volatile long oder mit einem AtomicLong? Wieso den?

Im Moment habe ich eine volatile long Aber fragte sich, ob ein anderer Ansatz besser wäre. Ich erhöhe auch meine lange, indem ich es mache ++counter im Gegensatz zu counter++. Ist das wirklich effizienter (wie ich anderswo glauben geführt wurde), weil keine Aufgabe erfolgt?

War es hilfreich?

Lösung

Angesichts dieser Anforderungen, i denken das a volatile lang sollte ausreichen. Der Zähler wäre mit einem Nichts nicht falschvolatile Lang, aber der Leser könnte in diesem Fall abgestandene Informationen lesen.

Ein Problem ist, dass es liest und auf a schreibt long sind nicht erforderlich Atomic sein, bis zum JVM -Spezifikation Wenn es nicht deklariert wird volatile. Das würde bedeuten, dass der Lese -Thread einen ziemlich fiktiven Wert erzielen könnte, wenn er den Wert liest, während der Schreib -Thread einen Teil des Wertes aktualisiert hat, aber nicht den anderen.

Der Unterschied zwischen ++counter und counter++ ist wahrscheinlich irrelevant, da der JVM erkennen wird, dass der Wert des Ausdrucks nicht mehr verwendet wird und die beiden in diesem Fall gleichwertig sind.

Andere Tipps

Verwenden Sie in Java 8 Longadder, was sogar noch besser ist als Atomiclong, wo die Gewinne hoch ist.

Longadder Javadoc:

Diese Klasse ist Atomiclong normalerweise vorzuziehen, wenn mehrere Threads eine gemeinsame Summe aktualisieren, die für Zwecke wie das Sammeln von Statistiken und nicht für die feinkörnige Synchronisationskontrolle verwendet wird. Unter geringer Aktualisierung weisen die beiden Klassen ähnliche Eigenschaften auf. Unter hoher Aussage ist der erwartete Durchsatz dieser Klasse auf Kosten eines höheren Raumverbrauchs signifikant höher.

Was ist die Verfügbarkeit für Ihr Programm? Könnten Sie mit einem unflüchtigen Int- und Racy-Lesen auskommen?

10^4 Inkremente / Sekunde ist 1 100 usec. Effizienz ist kein Problem, aber Atomizität könnte sein. Möglicherweise haben Sie 2 Kopien davon, und wenn es gelesen wird, wenn sie nicht gleich sind, lesen Sie erneut.

Dies Artikel Gespräche über die möglichen Möglichkeiten zur Implementierung eines Zählers. Ich denke, diese Implementierung sollte für Sie funktionieren

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

}

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top