2009-07-29 2 views
1

In dem Buch Java Servlet Programming gibt es ein Beispiel-Servlet auf Seite 54, das nach Primzahlen in einem Hintergrundthread sucht. Jedes Mal, wenn ein Client auf das Servlet zugreift, wird die zuletzt gefundene Primzahl zurückgegeben.Muss eine Variable, auf die mehrere Threads in einem Java-Servlet zugreifen, als flüchtig deklariert werden?

Die Variablen, die die zuletzt prime als solche erklärt wird festgestellt, zu speichern, verwendet wird:

long lastprime = 0; 

Da diese Variablen von mehreren Threads (dem Hintergrund-Thread zugegriffen werden beginnen, der die Berechnungen und jedes Client-Threads ist zu tun, dass greifen darauf zu), muss es nicht als flüchtig deklariert werden oder muss sein Zugang irgendwie synchronisiert sein?

Antwort

8

Ja, vorausgesetzt, Sie möchten wirklich die zuletzt berechnete Primzahl in einem beliebigen Thread sehen, sie sollte entweder flüchtig sein oder thread-sicher über synchronized Blöcke/Methoden zugegriffen werden. Wie in den Kommentaren erwähnt, werden nicht-volatile long-Variablen möglicherweise nicht atomar aktualisiert - so können Sie die oberen 32 Bits eines alten Werts und die unteren 32 Bits eines neuen Werts (oder umgekehrt) sehen.

vergaß ich über die Unteilbarkeit Seite der Dinge früher, weil es fast immer automatisch gelöst ist, wenn Sie Sie sicherstellen, dass die zuletzt veröffentlichten Wert erhalten, und stellen Sie sicher, dass Sie völlig neue Werte veröffentlichen. In der Praxis ist dies fast immer das, was Sie wollen, also wird Atomizität zu einem Nicht-Problem, wenn Ihr Code anfangs richtig funktioniert.

Es ist kein SingleThreadModel Servlet ist es? Das würde offensichtlich einen Unterschied machen. Eine andere Alternative wäre AtomicLong zu verwenden.

+1

Ich würde für AtomicLong wählen –

+0

Nein, es ist kein SingleThreadModel-Servlet. Es ist ein Beispiel für die Verwendung eines Servlets zur Hintergrundverarbeitung. – MCS

+0

Hört sich an, als wäre es nur ein schlechtes Beispiel. Es passiert - die Autoren wissen nie, worüber sie sprechen;) –

1

Ja. Die Variablen eines Servlets sind nicht Thread-sicher.

1

Es gibt eine saubere Lese-/Schreibaufteilung zwischen den Threads; Ein Thread "veröffentlicht" den letzten Prime, damit andere ihn lesen können.

Wenn das Zugriffsmuster einige Read-Modify-Write-Sequenzen oder ähnliches beinhaltete, müssten Sie den Zugriff auf das Feld synchronisieren.

1

Angenommen, Java 5 oder später deklariert dann Deklaration es flüchtig gibt wohldefinierte Semantik wie beschrieben here. Nach dem Prinzip, Zweifel aus dem Kopf des Code-Betreuers zu entfernen, würde ich volatile verwenden und sagen: "Ja, ich weiß, dass mehrere Threads diese Variable verwenden".

Die interessante Frage ist der Effekt, es nicht volatil zu deklarieren. Vorausgesetzt, Sie haben ein Prime, ist es wichtig, ob es das neueste verfügbare ist? Volatile stellt sicher, dass die Werte aus dem Speicher genommen werden, nicht aus irgendwelchen "CPU" -Caches, daher sollten Sie einen aktuelleren Wert erhalten.

Wie sieht es mit der Möglichkeit aus, eine Teilzuteilung zu sehen? Könnten Sie wirklich Pech haben und einen Long sehen, dessen LSBs Teil eines alten Wertes und MSBs Teil eines anderen Wertes sind? Nun, Zuordnungen zu Longs und Doubles sind nicht atomar, also in der Theorie ja!

Ergo, flüchtig oder synchronisiert ist nicht nur ein nice-to-have ...Sie brauchen es

0

Semantics von flüchtigen Variable in Java nicht stark genug sind, um den Schrittbetrieb (lastprime ++) atomar zu machen, es sei denn, Sie garantieren können, dass die Variable nur aus einem einzigen Thread geschrieben wird - nicht im Fall des Servlets

Auf der anderen Seite ist die Verwendung von AtomicXXX-Variablen threadsicher, solange keine zusammengesetzten Operationen ausgeführt werden. Es wird ein Sicherheitsfenster geben, wenn mehr als eine atomare Variable aktualisiert wird, obwohl jeder Aufruf atomar ist.

Verwandte Themen