77

複数のスレッドが同期せずにSystem.out.println(String)を呼び出す場合、出力をインターリーブできますか?それとも、各行の書き込みはアトミックですか?APIは同期について言及していないので、これは可能と思われますか、それともバッファリングやVMメモリモデルなどによってインターリーブされた出力が妨げられていますか?

編集:

たとえば、各スレッドに次のものが含まれている場合:

System.out.println("ABC");

出力は次のように保証されています:

ABC
ABC

またはそれは可能性があります:

AABC
BC
4

4 に答える 4

71

APIドキュメントでは、System.outオブジェクトのスレッドセーフについては言及されておらず、PrintStream#println(String)メソッドについても言及されて いないため、スレッドセーフであると想定することはできません

ただし、特定のJVMの基盤となる実装がprintlnメソッドにスレッドセーフな関数を使用する可能性は十分にあります(たとえばprintf、glibc)。そのため、実際には、最初の例に従って出力が保証されます(常にABC\nABC\n文字が散在することはありません)。 2番目の例による)。ただし、JVMの実装は多数あり、JVM仕様に準拠する必要があるだけであり、その仕様以外の規則に準拠する必要はないことに注意してください。

説明したようにprintln呼び出しが散在しないようにする必要がある場合は、次のように手動で相互排除を強制する必要があります

public void safePrintln(String s) {
  synchronized (System.out) {
    System.out.println(s);
  }
}

もちろん、この例は単なる例示であり、「解決策」としてとらえるべきではありません。考慮すべき他の多くの要因があります。たとえば、上記のメソッドは、すべてのコードがそのメソッドを使用し、直接呼び出すものがないsafePrintln(...)場合にのみ安全です。System.out.println(...)

于 2012-02-27T04:00:58.000 に答える
24

OpenJDKソースコードはあなたの質問に答えます:

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

参照: http: //hg.openjdk.java.net/jdk6/jdk6/jdk/file/39e8fe7a0af1/src/share/classes/java/io/PrintStream.java

于 2012-05-06T05:01:35.500 に答える
13

OutputStreamビアを変更しない限り、System.setOutスレッドセーフです。

スレッドセーフですが、多くのスレッドに次System.outのように書き込むことができます。

Thread-1
  System.out.println("A");
  System.out.println("B");
  System.out.println("C");
Thread-2
  System.out.println("1");
  System.out.println("2");
  System.out.println("3");

読める

1
2
A
3
B
C

他の組み合わせの中で。

だからあなたの質問に答えるために:

書き込みを行うと(インスタンスSystem.outのロックを取得します)OutputStream、バッファに書き込み、すぐにフラッシュします。

ロックが解除されると、OutputStreamがフラッシュされて書き込まれます。のように異なる文字列を結合する場合はありません1A 2B

あなたの編集に答えるために編集してください:

それはでは起こりませんSystem.out.println。はPrintStream関数全体を同期するため、バッファーがいっぱいになり、アトミックにフラッシュされます。入ってくる新しいスレッドには、作業するための新しいバッファーがあります。

于 2012-02-27T03:37:29.417 に答える
3

明確にするために、2つのスレッドがあるとします。1つは印刷"ABC"し、もう1つは印刷します"DEF"。次のような出力は得られませADBECFんが、どちらかを得ることができます

ABC
DEF 

また

DEF
ABC
于 2012-02-27T04:04:06.380 に答える