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它是PrintWriter其构造函数文档中明确提到的超类,所有关键部分都在Writer实例本身或明确指定的对象上同步。因此Writer是明确的线程安全的......

不幸的是,PrintWriter子类文档没有明确做出这样的承诺。它继承了Writer锁对象,但无法知道任何附加或覆盖的方法是否仍然是线程安全的。

另一方面,据我所知,Sun/OpenJDKPrintWriter实现synchronized在几乎所有方法中都包含块。但这似乎不是明确记录的行为。

我宁愿安全行事并假设它PrintWriter不是线程安全的,也不愿依赖未记录的行为并从长远来看对此感到遗憾......

于 2012-06-17T16:04:27.837 回答
11

这不是完全相同的问题,也没有给出任何证据。

它还说 PrintWriter 是没有资格的线程安全的,而另一个答案有资格。在我看来,这需要澄清。

由于 OP 不理解(或者可能不相信)链接问题的答案,我将重申它们。

  • 主要规范(即 javadocs)没有说明该类是否是线程安全的。

  • 从阅读源代码可以清楚地看出,在所有相关操作都正确同步的意义上,它是线程安全的。

  • Oracle 不太可能故意更改实现以使其成为非线程安全的......在上述意义上。

  • 但是,在某些用例中 aPrintWriter可能不是完全线程安全的:

    • 如果单个PrinterWriter线程被多个线程使用,结果可能是线程输出的不可预知的交错;例如,如果他们使用 print 而不是 println。

    • 如果您有多个PrintWriter对象包装相同的底层流,则可能会由于PrintWriters 的内部使用而出现问题BufferedWriter

    • 如果您将PrintWriter.

总之,当前的PrintWriter实现(在 Oracle/OpenJDK 代码库中)是线程安全的,但在某些情况下您仍然需要小心。其他第 3 方 Java 实现(即不是从 OpenJDK 源代码树派生的)也有可能不是线程安全的。

涉及多个线程写入同一底层流的应用程序的线程安全性总是有细微差别的......


请注意,@KazekageGaara 找到的引用...

多次写入底层输出流的所有方法都在内部处理同步,因此对象是线程安全的。”PrintWriterPrintWriter

... 来自 O'Reilly 教科书 - Mark Grand 和 Jonathan Knudsen 的“Java Fundamental Classes Reference”。由于这不是 Sun / Oracle 的官方出版物,因此它没有任何权威性。

于 2012-06-17T15:56:19.727 回答
4

是的,它是线程安全的。我不明白为什么有些人说它不是线程安全的。它肯定有“锁定”成员,并且它的方法在该锁定对象下完全同步。

有人说 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 回答