Ist multi-thread-output aus dem System.aus.println interleaved
Wenn mehrere threads Ruf-System.aus.println(String) ohne Synchronisation, können Sie die Ausgabe-interleaved? Oder ist das schreiben in jeder Zeile atomic? Die API macht keine Erwähnung der Synchronisation, so scheint dies möglich, oder ist interleaved output verhindert durch Pufferung und/oder der VM-Speicher-Modell, etc.?
EDIT:
Zum Beispiel, wenn jeder thread enthält:
System.out.println("ABC");
ist die Leistung garantiert:
ABC
ABC
oder könnte es sein:
AABC
BC
- Immer der erste. Aber Lesen @John Vint Antwort, weil Sie wahrscheinlich nicht wollen Zeichenfolgen werden ausgespuckt, die alle über die Konsole.
- Bedenken Sie, dass selbst wenn beide System.aus.println und System.err.println synchronisiert werden, diese beiden sind nicht zueinander synchronisiert sich also System.err.println kann interleave mit System.aus.println geben, Sie trösten, dass nicht sein kann, was Sie erwarten.
- Eigentlich habe ich ziemlich oft erhalten, interleaved output (Ihr zeigte Fall 2), sowohl in IntelliJ Idea und Eclipse, trotz, was andere Leute Euch sagen (jdk 1.6).
- Sehr interessant, @mucaho. Wären Sie bereit, zur post, ein Programm und Transkript als eine Antwort?
- Leider bin ich nicht in der Lage zu extrahieren, ein kleines Beispielprogramm zu zeigen, aber ich kann link, den Sie auf einem test-Fall, der zeigt, interleaved output beim ausführen. Suchen Sie für leere Zeilen, die Zeile oberhalb (interleaved) werden die meisten sicherlich. führen Sie JNetRobust.DelayedTest. Stellen Sie sicher, dass die
DEBUG
- flag auf true in den ersten paar Zeilen. - Ja Ausgang-Mischungen mit mehreren threads
Du musst angemeldet sein, um einen Kommentar abzugeben.
Da die API-Dokumentation macht keine Erwähnung von thread-Sicherheit auf der
System.out
Objekt auch nicht diePrintStream#println(String)
Methode Sie können nicht davon ausgehen, dass es thread-sicher ist.Allerdings ist es durchaus möglich, dass die zugrunde liegende Umsetzung einer bestimmten JVM verwendet eine thread-safe-Funktion für die
println
Methode (z.B.printf ()
glibc), so dass in der Realität, der Ausgang wird garantiert nach Ihrem ersten Beispiel (immerABC\n
dannABC\n
nie durchsetzt Zeichen pro Ihrem zweiten Beispiel). Aber Bedenken Sie, dass es gibt viele JVM-Implementierungen und Sie werden nur benötigt, um sich an der JVM-Spezifikation, keine Konventionen außerhalb der spec.Wenn Sie müssen absolut sicherstellen, dass keine println-Aufrufe wird sich durchsetzen, wie Sie es beschreiben, dann müssen Sie erzwingen die gegenseitige Ausgrenzung manuell, zum Beispiel:
Natürlich, dieses Beispiel ist nur eine illustration und sollte nicht als "Lösung"; es gibt viele andere Faktoren zu berücksichtigen. Zum Beispiel, die
safePrintln(...)
obige Methode ist nur sicher, wenn alle code verwendet, der Methode und nichts fordertSystem.out.println(...)
direkt.println
eigentlich tut das, was Sie beschreiben, hier? Machen nicht, dass es thread-sicher in die gleiche Vene als Ihre Lösung?safePrintln
ist nicht sicherer als eine einfache print-Anweisung. Nur weil Sie synchronisieren auf ein bestimmtes Objekt, Sie sind nicht immer alle Sicherheit. Sie sind nur thread-sicher, wenn alle code Zugriff auf die Ressource, wird die Synchronisierung auf das gleiche Objekt. Aber unter der Annahme, dass alle code-Aufruf von print-Methoden der Synchronisierung, die auf derSystem.out
Instanz bringt Sie zurück, wo Sie begonnen haben. Weiter, dein code ist fehlerhaft, wie es liest dieSystem.out
variable zweimal. Wenn jemand anruftSystem.setOut(…)
Recht zwischen diesen beiden liest Sie die Synchronisierung bricht.synchronized
stellt den gegenseitigen Ausschluss und die thread-Sicherheit zwischen threads mit dem gleichen Objekt. Das ist, was es tut.System.out.println(s);
ohnesynchronized (System.out)
, so dass diese Methode nur funktioniert, wenn alle threads, die Einhaltung der Konvention um diese Methode zu verwenden (oder tunsynchronized
auf Ihre eigenen) statt ZugriffSystem.out
direkt und dass niemand ruftsetOut
. Das ist, warum die Synchronisation ist in der Regel in Kombination mit Verkapselung, die es nicht erlaubt den direkten Zugriff auf die Ressource.Die OpenJDK-Quellcode Antworten auf Ihre Frage:
Referenz: http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/39e8fe7a0af1/src/share/classes/java/io/PrintStream.java
Solange Sie sich nicht ändern, die
OutputStream
überSystem.setOut
es ist thread-sicher.Aber es ist thread-sicher, die Sie kann haben viele threads schreiben
System.out
so dassLesen kann
unter anderen Kombinationen.
Also um deine Frage zu beantworten:
Beim schreiben auf
System.out
– es eine Sperre auf derOutputStream
Beispiel - es wird dann schreiben auf den Puffer und Spülen Sie sofort.Sobald es die Sperre, die
OutputStream
geleert und geschrieben. Gäbe es nicht eine Instanz, wo du verschiedene strings trat wie1A 2B
.Bearbeiten zur Beantwortung Ihrer edit:
Dass würde nicht passieren, mit
System.out.println
. Da diePrintStream
synchronisiert die gesamte Funktion, wird es füllen Sie den Puffer und dann Spülen Sie es atomar. Jeder neue thread kommen, haben jetzt eine neue Puffer, mit zu arbeiten.synchronized
Nur um zu klären, sagen, Sie haben zwei threads, einer, der druckt
"ABC"
und ein anderer, der druckt"DEF"
. Sie werden nie wieder eine Ausgabe wie diese:ADBECF
, aber Sie könnte entwederoder
ABC
obenDEF
oderDEF
obenABC