13

次の場合:

public class CConsole {
  public static PrintWriter pw = new PrintWriter(System.out, true);
}

CConsole.pw.format("%d %d", x, y)スレッドセーフですか?つまり、複数のスレッドがこの呼び出しを使用でき、スレッドセーフであると説明されている場所はどこですか。PrintWriterクラスの説明にもformat()メソッドの説明にも表示されません。

4

6 に答える 6

13

この質問には簡単な答えはありません...

は、コンストラクタのドキュメントで、すべてのクリティカルセクションがインスタンス自体または明示的に指定されたオブジェクトのいずれかで同期することWriterを明示的に言及しているスーパークラスです。したがって、明示的にスレッドセーフです...PrintWriterWriterWriter

残念ながら、PrintWriterサブクラスのドキュメントではそのような約束は明示されていません。ロックオブジェクトを継承しWriterますが、追加のメソッドまたはオーバーライドされたメソッドがまだスレッドセーフであるかどうかを知る方法はありません。

一方、私が知る限り、Sun/OpenJDKのPrintWriter実装synchronizedにはほとんどすべてのメソッドにブロックが含まれています。しかし、これは明示的に文書化された動作ではないようです。

PrintWriter文書化されていない動作に依存して長期的にこれを後悔するよりも、安全にプレイしてスレッドセーフではないと想定したいのですが...

于 2012-06-17T16:04:27.837 に答える
11

それはまったく同じ質問ではなく、証拠もありません。

また、PrintWriterは資格がなくてもスレッドセーフであるのに対し、別の回答には資格があります。私の見解では、これは明確にする必要があります。

OPはリンクされた質問への回答を理解していない(またはおそらく信じていない)ので、私はそれらを言い直します。

  • 主要な仕様(つまり、javadocs)には、クラスがスレッドセーフであるかどうかは記載されていません。

  • ソースコードを読むと、関連するすべての操作が適切に同期されているという意味でスレッドセーフであることが明らかです。

  • 上記の意味で、Oracleが実装を意図的に変更してスレッドセーフではないようにすることはほとんどありません。

  • ただし、がPrintWriter完全にスレッドセーフではない可能性があるユースケースがあります。

    • 単一PrinterWriterのスレッドが複数のスレッドで使用されている場合、結果として、スレッドからの出力の予測できないインターリーブが発生する可能性があります。たとえば、printlnではなくprintを使用する場合。

    • 同じ基になるストリームをラップする複数のオブジェクトがある場合、の内部使用がPrintWriter原因で問題が発生する可能性があります。PrintWriterBufferedWriter

    • サブクラス化すると状況が変わる可能性がありますPrintWriter

要約すると、現在のPrintWriter実装(Oracle / OpenJDKコードベース)はスレッドセーフですが、状況によっては注意が必要です。他のサードパーティのJava実装(つまり、OpenJDKソースツリーから派生していないもの)がスレッドセーフではない可能性もあります。

同じ基になるストリームに書き込む複数のスレッドを含むアプリケーションのスレッドセーフは、常に微妙な違いがあります...


@KazekageGaaraが見つけた引用に注意してください...

「基になる出力ストリームに複数回書き込むすべてのメソッドはPrintWriter、内部で同期を処理するため、PrintWriterオブジェクトはスレッドセーフです。」

...はO'Reillyの教科書からのものです-MarkGrandとJonathanKnudsenによる「JavaFundamentalClassesReference 」 。これはSun/Oracleの公式出版物ではないため、決して決定的なものではありません。

于 2012-06-17T15:56:19.727 に答える
4

はい、スレッドセーフです。スレッドセーフではないと言う人がいる理由がわかりません。それは間違いなく'lock'メンバーを持っており、そのメソッドはそのlockオブジェクトの下で完全に同期されています。

PrintWriter.printメソッドはスレッドセーフではないと言う人もいますが、それは間違っています。PrintWriter.printはwrite()を呼び出しますが、これは間違いなくスレッドセーフです。writeメソッドが「lock」の下で同期されることは誰もが知っています。したがって、printメソッドは暗黙的/自然にスレッドセーフです。

PrintWriter.printlnは、print()とprintln()を呼び出すため、それ自体で同期されます。これらは両方とも「独立して」スレッドセーフです。

于 2013-06-04T03:27:30.440 に答える
2

ここから取られた、一行は言う:

基になる出力ストリームに複数回書き込むPrintWriterのすべてのメソッドは、内部で同期を処理するため、PrintWriterオブジェクトはスレッドセーフです。

于 2012-06-17T16:16:38.110 に答える
1
{ 
public void print(Object obj) 
     {

        write(String.valueOf(obj));
     }

     /* Methods that do terminate lines */

}

印刷が同期されていません...

したがって、印刷方法を使用している場合は、独自の「マイライター」を作成して同期します。

またはその他

println()....を使用すると、同期されます。

{

         public void println(Object x) {
         String s = String.valueOf(x);
         synchronized (lock) {
             print(s);
             println();
         }
     }

}
于 2013-05-21T17:27:57.950 に答える
0

いいえ、実際にはスレッドセーフではありません。

PrintWriter.javaのwrite()メソッドをここで参照してください

それらの書き込みはロックで同期されます(ここで定義されています-これはWriterオブジェクトです。これで同期された場合、スレッドセーフでしたが、この場合はそうではありません。

于 2012-06-17T15:49:17.943 に答える