次の場合:
public class CConsole {
public static PrintWriter pw = new PrintWriter(System.out, true);
}
CConsole.pw.format("%d %d", x, y)
スレッドセーフですか?つまり、複数のスレッドがこの呼び出しを使用でき、スレッドセーフであると説明されている場所はどこですか。PrintWriterクラスの説明にもformat()メソッドの説明にも表示されません。
次の場合:
public class CConsole {
public static PrintWriter pw = new PrintWriter(System.out, true);
}
CConsole.pw.format("%d %d", x, y)
スレッドセーフですか?つまり、複数のスレッドがこの呼び出しを使用でき、スレッドセーフであると説明されている場所はどこですか。PrintWriterクラスの説明にもformat()メソッドの説明にも表示されません。
この質問には簡単な答えはありません...
は、コンストラクタのドキュメントで、すべてのクリティカルセクションがインスタンス自体または明示的に指定されたオブジェクトのいずれかで同期することWriter
を明示的に言及しているスーパークラスです。したがって、明示的にスレッドセーフです...PrintWriter
Writer
Writer
残念ながら、PrintWriter
サブクラスのドキュメントではそのような約束は明示されていません。ロックオブジェクトを継承しWriter
ますが、追加のメソッドまたはオーバーライドされたメソッドがまだスレッドセーフであるかどうかを知る方法はありません。
一方、私が知る限り、Sun/OpenJDKのPrintWriter
実装synchronized
にはほとんどすべてのメソッドにブロックが含まれています。しかし、これは明示的に文書化された動作ではないようです。
PrintWriter
文書化されていない動作に依存して長期的にこれを後悔するよりも、安全にプレイしてスレッドセーフではないと想定したいのですが...
それはまったく同じ質問ではなく、証拠もありません。
また、PrintWriterは資格がなくてもスレッドセーフであるのに対し、別の回答には資格があります。私の見解では、これは明確にする必要があります。
OPはリンクされた質問への回答を理解していない(またはおそらく信じていない)ので、私はそれらを言い直します。
主要な仕様(つまり、javadocs)には、クラスがスレッドセーフであるかどうかは記載されていません。
ソースコードを読むと、関連するすべての操作が適切に同期されているという意味でスレッドセーフであることが明らかです。
上記の意味で、Oracleが実装を意図的に変更してスレッドセーフではないようにすることはほとんどありません。
ただし、がPrintWriter
完全にスレッドセーフではない可能性があるユースケースがあります。
単一PrinterWriter
のスレッドが複数のスレッドで使用されている場合、結果として、スレッドからの出力の予測できないインターリーブが発生する可能性があります。たとえば、printlnではなくprintを使用する場合。
同じ基になるストリームをラップする複数のオブジェクトがある場合、の内部使用がPrintWriter
原因で問題が発生する可能性があります。PrintWriter
BufferedWriter
サブクラス化すると状況が変わる可能性がありますPrintWriter
。
要約すると、現在のPrintWriter
実装(Oracle / OpenJDKコードベース)はスレッドセーフですが、状況によっては注意が必要です。他のサードパーティのJava実装(つまり、OpenJDKソースツリーから派生していないもの)がスレッドセーフではない可能性もあります。
同じ基になるストリームに書き込む複数のスレッドを含むアプリケーションのスレッドセーフは、常に微妙な違いがあります...
@KazekageGaaraが見つけた引用に注意してください...
「基になる出力ストリームに複数回書き込むすべてのメソッドは
PrintWriter
、内部で同期を処理するため、PrintWriter
オブジェクトはスレッドセーフです。」
...はO'Reillyの教科書からのものです-MarkGrandとJonathanKnudsenによる「JavaFundamentalClassesReference 」 。これはSun/Oracleの公式出版物ではないため、決して決定的なものではありません。
はい、スレッドセーフです。スレッドセーフではないと言う人がいる理由がわかりません。それは間違いなく'lock'メンバーを持っており、そのメソッドはそのlockオブジェクトの下で完全に同期されています。
PrintWriter.printメソッドはスレッドセーフではないと言う人もいますが、それは間違っています。PrintWriter.printはwrite()を呼び出しますが、これは間違いなくスレッドセーフです。writeメソッドが「lock」の下で同期されることは誰もが知っています。したがって、printメソッドは暗黙的/自然にスレッドセーフです。
PrintWriter.printlnは、print()とprintln()を呼び出すため、それ自体で同期されます。これらは両方とも「独立して」スレッドセーフです。
ここから取られた、一行は言う:
基になる出力ストリームに複数回書き込むPrintWriterのすべてのメソッドは、内部で同期を処理するため、PrintWriterオブジェクトはスレッドセーフです。
{
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();
}
}
}
いいえ、実際にはスレッドセーフではありません。
PrintWriter.javaのwrite()メソッドをここで参照してください
それらの書き込みはロックで同期されます(ここで定義されています-これはWriterオブジェクトです。これで同期された場合、スレッドセーフでしたが、この場合はそうではありません。